From 6af21e6a4f2251e71353562d5df7f376fdffc270 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Tue, 25 Mar 2025 17:36:52 -0400 Subject: initial checkout from wrc --- 0.S | 11 + 0.c | 35 + 0.h | 38 + BuildImage | Bin 0 -> 22896 bytes MK | 36 + MKV | 36 + Makefile | 319 +++ QRUN | 16 + boot/Make.mk | 43 + boot/boot.S | 666 ++++++ doc/Memory.txt | 92 + doc/NOTES | 162 ++ doc/user_image.txt | 5841 +++++++++++++++++++++++++++++++++++++++++++++ doc/usermatrix.txt | 53 + include/bootstrap.h | 120 + include/cio.h | 287 +++ include/clock.h | 55 + include/common.h | 31 + include/compat.h | 131 + include/debug.h | 324 +++ include/defs.h | 129 + include/elf.h | 235 ++ include/kdefs.h | 146 ++ include/klib.h | 57 + include/kmem.h | 138 ++ include/lib.h | 287 +++ include/list.h | 68 + include/params.h | 31 + include/procs.h | 452 ++++ include/sio.h | 168 ++ include/support.h | 87 + include/syscalls.h | 80 + include/types.h | 58 + include/udefs.h | 113 + include/ulib.h | 315 +++ include/user.h | 138 ++ include/userids.h | 33 + include/vm.h | 433 ++++ include/vmtables.h | 43 + include/x86/arch.h | 303 +++ include/x86/bios.h | 73 + include/x86/ops.h | 443 ++++ include/x86/pic.h | 139 ++ include/x86/pit.h | 82 + include/x86/uart.h | 349 +++ kernel/Make.mk | 66 + kernel/cio.c | 796 ++++++ kernel/clock.c | 163 ++ kernel/isrs.S | 374 +++ kernel/kernel.c | 381 +++ kernel/kernel.ld | 57 + kernel/kmem.c | 681 ++++++ kernel/list.c | 64 + kernel/procs.c | 1136 +++++++++ kernel/sio.c | 694 ++++++ kernel/startup.S | 153 ++ kernel/support.c | 279 +++ kernel/syscalls.c | 829 +++++++ kernel/user.c | 774 ++++++ kernel/vm.c | 585 +++++ kernel/vmtables.c | 270 +++ lib/Make.mk | 73 + lib/bound.c | 37 + lib/cvtdec.c | 43 + lib/cvtdec0.c | 44 + lib/cvthex.c | 49 + lib/cvtoct.c | 54 + lib/cvtuns.c | 37 + lib/cvtuns0.c | 39 + lib/entry.S | 25 + lib/klibc.c | 112 + lib/memclr.c | 37 + lib/memcpy.c | 41 + lib/memset.c | 38 + lib/pad.c | 35 + lib/padstr.c | 61 + lib/sprint.c | 133 ++ lib/str2int.c | 51 + lib/strcat.c | 38 + lib/strcmp.c | 32 + lib/strcpy.c | 35 + lib/strlen.c | 32 + lib/ulibc.c | 162 ++ lib/ulibs.S | 93 + user/Make.mk | 64 + user/README | 25 + user/idle.c | 51 + user/init.c | 185 ++ user/progABC.c | 68 + user/progDE.c | 56 + user/progFG.c | 55 + user/progH.c | 66 + user/progI.c | 104 + user/progJ.c | 52 + user/progKL.c | 61 + user/progMN.c | 72 + user/progP.c | 51 + user/progQ.c | 43 + user/progR.c | 99 + user/progS.c | 50 + user/progTUV.c | 169 ++ user/progW.c | 57 + user/progX.c | 48 + user/progY.c | 49 + user/progZ.c | 57 + user/shell.c | 343 +++ user/user.ld | 51 + util/BuildImage.c | 415 ++++ util/Make.mk | 59 + util/Offsets.c | 250 ++ util/alternatives/Make.mk | 56 + util/alternatives/README | 31 + util/alternatives/kmem.c | 749 ++++++ util/alternatives/lib.c | 56 + util/gdbinit.tmpl | 31 + util/listblob.c | 248 ++ util/mergedep.pl | 86 + util/mkblob.c | 324 +++ vmtables.d | 5 + 119 files changed, 25485 insertions(+) create mode 100644 0.S create mode 100644 0.c create mode 100644 0.h create mode 100755 BuildImage create mode 100755 MK create mode 100755 MKV create mode 100644 Makefile create mode 100755 QRUN create mode 100644 boot/Make.mk create mode 100644 boot/boot.S create mode 100644 doc/Memory.txt create mode 100644 doc/NOTES create mode 100644 doc/user_image.txt create mode 100644 doc/usermatrix.txt create mode 100644 include/bootstrap.h create mode 100644 include/cio.h create mode 100644 include/clock.h create mode 100644 include/common.h create mode 100644 include/compat.h create mode 100644 include/debug.h create mode 100644 include/defs.h create mode 100644 include/elf.h create mode 100644 include/kdefs.h create mode 100644 include/klib.h create mode 100644 include/kmem.h create mode 100644 include/lib.h create mode 100644 include/list.h create mode 100644 include/params.h create mode 100644 include/procs.h create mode 100644 include/sio.h create mode 100644 include/support.h create mode 100644 include/syscalls.h create mode 100644 include/types.h create mode 100644 include/udefs.h create mode 100644 include/ulib.h create mode 100644 include/user.h create mode 100644 include/userids.h create mode 100644 include/vm.h create mode 100644 include/vmtables.h create mode 100644 include/x86/arch.h create mode 100644 include/x86/bios.h create mode 100644 include/x86/ops.h create mode 100644 include/x86/pic.h create mode 100644 include/x86/pit.h create mode 100644 include/x86/uart.h create mode 100644 kernel/Make.mk create mode 100644 kernel/cio.c create mode 100644 kernel/clock.c create mode 100644 kernel/isrs.S create mode 100644 kernel/kernel.c create mode 100644 kernel/kernel.ld create mode 100644 kernel/kmem.c create mode 100644 kernel/list.c create mode 100644 kernel/procs.c create mode 100644 kernel/sio.c create mode 100644 kernel/startup.S create mode 100644 kernel/support.c create mode 100644 kernel/syscalls.c create mode 100644 kernel/user.c create mode 100644 kernel/vm.c create mode 100644 kernel/vmtables.c create mode 100644 lib/Make.mk create mode 100644 lib/bound.c create mode 100644 lib/cvtdec.c create mode 100644 lib/cvtdec0.c create mode 100644 lib/cvthex.c create mode 100644 lib/cvtoct.c create mode 100644 lib/cvtuns.c create mode 100644 lib/cvtuns0.c create mode 100644 lib/entry.S create mode 100644 lib/klibc.c create mode 100644 lib/memclr.c create mode 100644 lib/memcpy.c create mode 100644 lib/memset.c create mode 100644 lib/pad.c create mode 100644 lib/padstr.c create mode 100644 lib/sprint.c create mode 100644 lib/str2int.c create mode 100644 lib/strcat.c create mode 100644 lib/strcmp.c create mode 100644 lib/strcpy.c create mode 100644 lib/strlen.c create mode 100644 lib/ulibc.c create mode 100644 lib/ulibs.S create mode 100644 user/Make.mk create mode 100644 user/README create mode 100644 user/idle.c create mode 100644 user/init.c create mode 100644 user/progABC.c create mode 100644 user/progDE.c create mode 100644 user/progFG.c create mode 100644 user/progH.c create mode 100644 user/progI.c create mode 100644 user/progJ.c create mode 100644 user/progKL.c create mode 100644 user/progMN.c create mode 100644 user/progP.c create mode 100644 user/progQ.c create mode 100644 user/progR.c create mode 100644 user/progS.c create mode 100644 user/progTUV.c create mode 100644 user/progW.c create mode 100644 user/progX.c create mode 100644 user/progY.c create mode 100644 user/progZ.c create mode 100644 user/shell.c create mode 100644 user/user.ld create mode 100644 util/BuildImage.c create mode 100644 util/Make.mk create mode 100644 util/Offsets.c create mode 100644 util/alternatives/Make.mk create mode 100644 util/alternatives/README create mode 100644 util/alternatives/kmem.c create mode 100644 util/alternatives/lib.c create mode 100644 util/gdbinit.tmpl create mode 100644 util/listblob.c create mode 100644 util/mergedep.pl create mode 100644 util/mkblob.c create mode 100644 vmtables.d diff --git a/0.S b/0.S new file mode 100644 index 0000000..1fe8335 --- /dev/null +++ b/0.S @@ -0,0 +1,11 @@ +/** +** @file ? +** +** @author CSCI-452 class of 20245 +** +** @brief ? +*/ + +#define ASM_SRC + + .arch i386 diff --git a/0.c b/0.c new file mode 100644 index 0000000..f5dae52 --- /dev/null +++ b/0.c @@ -0,0 +1,35 @@ +/** +** @file ? +** +** @author CSCI-452 class of 20245 +** +** @brief ? +*/ + +#define KERNEL_SRC + +#include + +/* +** PRIVATE DEFINITIONS +*/ + +/* +** PRIVATE DATA TYPES +*/ + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +/* +** PRIVATE FUNCTIONS +*/ + +/* +** PUBLIC FUNCTIONS +*/ diff --git a/0.h b/0.h new file mode 100644 index 0000000..217b580 --- /dev/null +++ b/0.h @@ -0,0 +1,38 @@ +/** +** @file ? +** +** @author CSCI-452 class of 20245 +** +** @brief ? +*/ + +#ifndef ?_H_ +#define ?_H_ + +#include + +/* +** General (C and/or assembly) definitions +*/ + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Types +*/ + +/* +** Globals +*/ + +/* +** Prototypes +*/ + +#endif /* !ASM_SRC */ + +#endif diff --git a/BuildImage b/BuildImage new file mode 100755 index 0000000..c281af3 Binary files /dev/null and b/BuildImage differ diff --git a/MK b/MK new file mode 100755 index 0000000..347f885 --- /dev/null +++ b/MK @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Run 'make', saving all output into a file named LOG +# +# usage: +# MK [args] - prints timestamps and status +# MKV [args] - echoes and saves 'make' output +# + +# remember this so we know what to do +name="`basename $0`" + +# starting timestamp +time1="`date`" + +if [ "$name" = "MK" ] +then + # run make, save output, check status + echo -n + make $* '> LOG 2>&1 ... ' + if make $* > LOG 2>&1 + then + echo done + else + echo check LOG for build errors + fi +else + # just do the make and save a copy of the output + echo + make $* '2>&1 | tee LOG' + make $* 2>&1 | tee LOG +fi + +# ending timestamp +time2="`date`" + +echo Start: $time1 +echo "End: " $time2 diff --git a/MKV b/MKV new file mode 100755 index 0000000..347f885 --- /dev/null +++ b/MKV @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Run 'make', saving all output into a file named LOG +# +# usage: +# MK [args] - prints timestamps and status +# MKV [args] - echoes and saves 'make' output +# + +# remember this so we know what to do +name="`basename $0`" + +# starting timestamp +time1="`date`" + +if [ "$name" = "MK" ] +then + # run make, save output, check status + echo -n + make $* '> LOG 2>&1 ... ' + if make $* > LOG 2>&1 + then + echo done + else + echo check LOG for build errors + fi +else + # just do the make and save a copy of the output + echo + make $* '2>&1 | tee LOG' + make $* 2>&1 | tee LOG +fi + +# ending timestamp +time2="`date`" + +echo Start: $time1 +echo "End: " $time2 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..67353ce --- /dev/null +++ b/Makefile @@ -0,0 +1,319 @@ +# +# Makefile for the 20245 operating system. +# + +######################################## +# Compilation/assembly definable options +######################################## + +# +# General options: +# CLEAR_BSS include code to clear all BSS space +# GET_MMAP get BIOS memory map via int 0x15 0xE820 +# OS_CONFIG OS-related (vs. just standalone) variations +# FORCE_INLINING force "inline" functions to be inlined even if +# we aren't compiling with at least -O2 +# MAKE_IDENTITY_MAP Compile vmtables.c with an "identity" page +# map table for the first 4MB of the address space. +# + +GEN_OPTIONS = -DCLEAR_BSS -DGET_MMAP -DOS_CONFIG + +# +# Debugging options: +# ANNOUNCE_ENTRY announce entry and exit from kernel functions +# RPT_INT_UNEXP report any 'unexpected' interrupts +# RPT_INT_MYSTERY report interrupt 0x27 specifically +# TRACE_CX context restore tracing +# SANITY=n enable "sanity check" level 'n' (0/1/2/3/4) +# T_* tracing options (see below) +# +# Some modules have their own internal debugging options, described +# in their introductory comments. +# +# Define SANITY as 0 for minimal runtime checking (critical errors only). +# If not defined, SANITY defaults to 9999. +# + +DBG_OPTIONS = -DRPT_INT_UNEXP +# DBG_OPTIONS += -DTRACE_CX + +# +# T_ options are used to define bits in a "tracing" bitmask, to allow +# checking of individual conditions. The following are defined: +# +# T_PCB PCB alloc/dealloc +# T_VM VM-related tasks +# T_QUE PCB queue manipulation +# T_SCH, T_DSP Scheduler and dispatcher +# T_SCALL, T_SRET System call entry and exit +# T_EXIT Process exit actions +# T_FORK, T_EXEC Fork and exec actions +# T_INIT Module init function tracing +# T_KM, T_KMFR, T_KMIN Kmem module tracing +# T_SIO, T_SIOR, T_SIOW General SIO module checks +# T_USER, T_ELF User module operations +# +# You can add compilation options "on the fly" by using EXTRAS=thing +# on the command line. For example, to compile with -H (to show the +# hierarchy of #includes): +# +# make EXTRAS=-H +# + +TRACE_OPTIONS = -DT_INIT -DT_USER -DT_ELF -DT_KMIN -DT_VM + +USER_OPTIONS = $(GEN_OPTIONS) $(DBG_OPTIONS) $(TRACE_OPTIONS) $(EXTRAS) + +############################################################## +# YOU SHOULD NOT NEED TO CHANGE ANYTHING BELOW THIS POINT!!! # +############################################################## + +# +# Compilation/assembly control +# + +# +# We only want to include from the common header directory +# +INCLUDES = -I./include + +# +# All our object code will live here +# +BUILDDIR = build +LIBDIR = $(BUILDDIR)/lib + +# +# Things we need to convert to object form +# +SUBDIRS := + +# +# Compilation/assembly/linking commands and options +# +CPP = cpp +CPPFLAGS = $(USER_OPTIONS) -nostdinc $(INCLUDES) + +# +# Compiler/assembler/etc. settings for 32-bit binaries +# +CC = gcc -pipe +CFLAGS = -m32 -fno-pie -std=c99 -fno-stack-protector -fno-builtin -Wall -Wstrict-prototypes -MD $(CPPFLAGS) +# CFLAGS += -O2 + +AS = as +ASFLAGS = --32 + +LD = ld +LDFLAGS = -melf_i386 -no-pie -nostdlib -L$(LIBDIR) + +AR = ar +#ARFLAGS = rvU +ARFLAGS = rsU + +# other programs we use +OBJDUMP = objdump +OBJCOPY = objcopy +NM = nm +READELF = readelf +PERL = perl + +# delete target files if there is an error, or if make is interrupted +.DELETE_ON_ERROR: + +# don't delete intermediate files +.PRECIOUS: %.o $(BUILDDIR)/boot/%.o $(BUILDDIR)/kernel/%.o \ + $(BUILDDIR)/lib/%.o $(BUILDDIR)/user/%.o + +# +# Update $(BUILDDIR)/.vars.X if variable X has changed since the last time +# 'make' was run. +# +# Rules that use variable X should depend on $(BUILDDIR)/.vars.X. If +# the variable's value has changed, this will update the vars file and +# force a rebuild of the rule that depends on it. +# + +$(BUILDDIR)/.vars.%: FORCE + echo "$($*)" | cmp -s $@ || echo "$($*)" > $@ + +.PRECIOUS: $(BUILDDIR)/.vars.% + +.PHONY: FORCE + +# +# Transformation rules - these ensure that all necessary compilation +# flags are specified +# +# Note use of 'cpp' to convert .S files to temporary .s files: this allows +# use of #include/#define/#ifdef statements. However, the line numbers of +# error messages reflect the .s file rather than the original .S file. +# (If the .s file already exists before a .S file is assembled, then +# the temporary .s file is not deleted. This is useful for figuring +# out the line numbers of error messages, but take care not to accidentally +# start fixing things by editing the .s file.) +# +# The .c.X rule produces a .X file which contains the original C source +# code from the file being compiled mixed in with the generated +# assembly language code. Can be helpful when you need to figure out +# exactly what C statement generated which assembly statements! +# + +.SUFFIXES: .S .b .X .i + +.c.X: + $(CC) $(CFLAGS) -g -c -Wa,-adhln $*.c > $*.X + +.c.s: + $(CC) $(CFLAGS) -S $*.c + +#.S.s: +# $(CPP) $(CPPFLAGS) -o $*.s $*.S + +#.S.o: +# $(CPP) $(CPPFLAGS) -o $*.s $*.S +# $(AS) $(ASFLAGS) -o $*.o $*.s -a=$*.lst +# $(RM) -f $*.s + +.s.b: + $(AS) $(ASFLAGS) -o $*.o $*.s -a=$*.lst + $(LD) $(LDFLAGS) -Ttext 0x0 -s --oformat binary -e begtext -o $*.b $*.o + +#.c.o: +# $(CC) $(CFLAGS) -c $*.c + +.c.i: + $(CC) -E $(CFLAGS) -c $*.c > $*.i + +# +# Location of the QEMU binary +# +QEMU = /home/course/csci352/bin/qemu-system-i386 + +# try to generate a unique GDB port +GDBPORT = $(shell expr `id -u` % 5000 + 25000) + +# QEMU's gdb stub command line changed in 0.11 +QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \ + then echo "-gdb tcp::$(GDBPORT)"; \ + else echo "-s -p $(GDBPORT)"; fi) + +# options for QEMU +# +# run 'make' with -DQEMUEXTRA=xxx to add option 'xxx' when QEMU is run +# +# does not include a '-serial' option, as that may or may not be needed +QEMUOPTS = -drive file=disk.img,index=0,media=disk,format=raw $(QEMUEXTRA) + +######################################## +# RULES SECTION +######################################## + +# +# All the individual parts +# + +# +# We have a bit of a chicken/egg problem here. When we create the +# user.img file, a new version of include/userids.h is generated +# in build/new_userids.h; this is compared to the existing userids.h +# file, and if they differ, it is copied into include/userids.h. +# This, unfortunately, should trigger a rebuild of anything that +# includes , but that is all of the user/*.c files along +# with kernel/kernel.c. We could move the user.img creation earlier, +# which would automatically be incorporated into the build of the +# kernel, but it wouldn't automatically trigger recreating the +# userland stuff. We settle for having the build process tell the +# user that a rebuild is required. +# + +all: lib bootstrap kernel userland util user.img disk.img + +# Rules etc. for the various sections of the system +include lib/Make.mk +include boot/Make.mk +include user/Make.mk +include kernel/Make.mk +include util/Make.mk + +# +# Rules for building the disk image +# + +disk.img: $(BUILDDIR)/kernel/kernel.b $(BUILDDIR)/boot/boot user.img BuildImage + ./BuildImage -d usb -o disk.img -b $(BUILDDIR)/boot/boot \ + $(BUILDDIR)/kernel/kernel.b 0x10000 \ + user.img 0x30000 + +# +# Rules for running with QEMU +# + +# how to create the .gdbinit config file if we need it +.gdbinit: util/gdbinit.tmpl + sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@ + +# "ordinary" gdb +gdb: + gdb -q -n -x .gdbinit + +# gdb with the super-fancy Text User Interface +gdb-tui: + gdb -q -n -x .gdbinit -tui + +qemu: disk.img + $(QEMU) -serial mon:stdio $(QEMUOPTS) + +qemu-nox: disk.img + $(QEMU) -nographic $(QEMUOPTS) + +qemu-gdb: disk.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -serial mon:stdio $(QEMUOPTS) -S $(QEMUGDB) + +qemu-nox-gdb: disk.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB) + +# +# Create a printable namelist from the kernel file +# +# kernel.nl: only global symbols +# kernel.nll: all symbols +# + +kernel.nl: $(BUILDDIR)/kernel/kernel + nm -Bng $(BUILDDIR)/kernel/kernel.o | pr -w80 -3 > kernel.nl + +kernel.nll: $(BUILDDIR)/kernel/kernel + nm -Bn $(BUILDDIR)/kernel/kernel.o | pr -w80 -3 > kernel.nll + +# +# Generate a disassembly +# + +kernel.dis: $(BUILDDIR)/kernel/kernel + objdump -d $(BUILDDIR)/kernel/kernel > kernel.dis + +# +# Cleanup etc. +# + +clean: + rm -rf $(BUILDDIR) .gdbinit *.nl *.nll *.lst *.i *.X *.dis + +realclean: clean + rm -f LOG *.img $(UTIL_BIN) + +# +# Automatically generate dependencies for header files included +# from C source files. +# +$(BUILDDIR)/.deps: $(foreach dir, $(SUBDIRS), $(wildcard $(BUILDDIR)/$(dir)/*.d)) + @mkdir -p $(@D) + $(PERL) util/mergedep.pl $@ $^ + +-include $(BUILDDIR)/.deps + +.PHONY: all clean realclean diff --git a/QRUN b/QRUN new file mode 100755 index 0000000..c42c44d --- /dev/null +++ b/QRUN @@ -0,0 +1,16 @@ +#!/bin/bash +# +# Run qemu-system-i386 on the baseline OS +# + +# +# other options: +# -nographic +# -display gtk +# + +QEMU=/home/course/csci352/bin/qemu-system-i386 + +exec $QEMU \ + -serial mon:stdio \ + -drive file=disk.img,index=0,media=disk,format=raw diff --git a/boot/Make.mk b/boot/Make.mk new file mode 100644 index 0000000..a7396fb --- /dev/null +++ b/boot/Make.mk @@ -0,0 +1,43 @@ +# +# Makefile fragment for the bootstrap component of the system. +# +# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level +# directory, and this will be pulled in automatically. +# + +SUBDIRS += boot + +################### +# FILES SECTION # +################### + +BOOT_SRC := boot/boot.S + +BOOT_OBJ := $(BUILDDIR)/boot/boot.o + +# BLDFLAGS := -Ttext 0x7c00 -s --oformat binary -e bootentry +# BLDFLAGS := -Ttext 0 -s --oformat binary -e bootentry +# BLDFLAGS := -N -Ttext 0x7c00 -s -e bootentry +BLDFLAGS := -N -Ttext 0 -s -e bootentry + +################### +# RULES SECTION # +################### + +bootstrap: $(BUILDDIR)/boot/boot + +$(BUILDDIR)/boot/%.o: boot/%.c $(BUILDDIR)/.vars.CFLAGS + @mkdir -p $(@D) + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILDDIR)/boot/%.o: boot/%.S $(BUILDDIR)/.vars.CFLAGS + @mkdir -p $(@D) + $(CPP) $(CPPFLAGS) -o $(@D)/$*.s $< + $(AS) $(ASFLAGS) -o $@ $(@D)/$*.s -a=$(@D)/$*.lst + $(RM) -f $(@D)/$*.s + $(NM) -n $@ > $(@D)/$*.sym + +$(BUILDDIR)/boot/boot: $(BOOT_OBJ) + @mkdir -p $(@D) + $(LD) $(LDFLAGS) $(BLDFLAGS) -o $@.out $^ + $(OBJCOPY) -S -O binary -j .text $@.out $@ diff --git a/boot/boot.S b/boot/boot.S new file mode 100644 index 0000000..50d6188 --- /dev/null +++ b/boot/boot.S @@ -0,0 +1,666 @@ +/** +** SCCS ID: @(#)boot.S 2.4 1/22/25 +** +** @file boot.S +** +** @author Jon Coles +** copyleft 1999 Jon Coles +** +** @author Warren R. Carithers, K. Reek, Garrett C. Smith +** @author Walter Litwinczyk, David C. Larsen, Sean T. Congden +** +** Bootstrap routine. +** +** This bootstrap program is loaded by the PC BIOS into memory at +** location 0000:7C00. It must be exactly 512 bytes long, and must +** end with the hex sequence AA55 at location 1FE. +** +** The bootstrap initially sets up a stack in low memory. Next, it +** loads a second sector at 0000:7E00 (immediately following the +** boot block). Then it loads the target program at TARGET_ADDR, +** switches to protected mode, and branches to the target program. +** +** NOTE: To zero out the BSS segment, define CLEAR_BSS when this code +** is assembled. +** +** Must assemble this as 16-bit code. +*/ + .code16 + +#define ASM_SRC + +#include +#include +#include + +/* +** Symbol for locating the beginning of the code. +*/ + .globl bootentry + + .text +bootentry: + +/* +** Entry point. Disable interrupts and set up a runtime stack. +*/ + cli + + movw $BOOT_SEG, %ax /* data seg. base address */ + movw %ax, %ds + movw %ax, %ss /* also stack seg. base */ + movw $BOOT_SP_DISP, %ax + movw %ax, %sp + +/* +** Next, verify that the disk is there and working. +*/ + movb $BD_CHECK, %ah /* test the disk status and make sure */ + movb drive, %dl /* it's safe to proceed */ + int $BIOS_DISK + jnc diskok + + movw $err_diskstatus, %si /* Something went wrong; print a message */ + call dispMsg /* and freeze. */ + jmp . + +/* +** The disk is there. Reset it, and retrieve the disk parameters. +*/ +diskok: + movw $BD_RESET, %ax /* Reset the disk */ + movb drive, %dl + int $BIOS_DISK + + /* determine number of heads and sectors/track */ + xorw %ax, %ax /* set ES:DI = 0000:0000 in case of BIOS bugs */ + movw %ax, %es + movw %ax, %di + movb $BD_PARAMS, %ah /* get drive parameters */ + movb drive, %dl /* hard disk or floppy */ + int $BIOS_DISK + + /* store (max + 1) - CL[5:0] = maximum head, DH = maximum head */ + andb $0x3F, %cl + incb %cl + incb %dh + + movb %cl, max_sec + movb %dh, max_head + +/* +** The disk is OK, so we now need to load the second half of the bootstrap. +** It must immediately follow the boot sector on the disk, and the target +** program(s) must immediately follow that. +*/ + movw $msg_loading, %si /* Print the Loading message */ + call dispMsg + + movw $1, %ax /* sector count = 1 */ + movw $BOOT_SEG, %bx /* read this into memory that */ + movw %bx, %es /* immediately follows this code. */ + movw $PART2_DISP, %bx + call readprog + +/* +** We've got the second block of the bootstrap program in memory. Now +** read all of the user's program blocks. Use %di to point to the +** count field for the next block to load. +*/ + movw $k_sect, %di + + pushw %ds + movw (%di), %bx + movw $MMAP_SEG, %ax + movw %ax, %ds + movw %bx, MMAP_SECTORS /* store kernel image size */ + popw %ds + +/* +** Each target program has three values in the array at the end of the +** second half of the bootstrap: the offset and segment base address +** where the program should go, and the sector count. +*/ +nextblock: + movw (%di), %ax /* get the # of sectors */ + testw %ax, %ax /* is it zero? */ + jz done_loading /* yes, nothing more to load. */ + + subw $2, %di + movw (%di), %bx /* get the segment value */ + movw %bx, %es /* and copy it to %es */ + subw $2, %di + movw (%di), %bx /* get the address offset */ + subw $2, %di + pushw %di /* save di */ + call readprog /* read this program block, */ + popw %di /* and restore di */ + jmp nextblock /* then go back and read the next one. */ + +/* +** Read one complete program block into memory. +** +** ax: number of sectors to read +** es:bx = starting address for the block +*/ +readprog: + pushw %ax /* save sector count */ + + movw $3, %cx /* initial retry count is 3 */ +retry: + pushw %cx /* push the retry count on the stack. */ + + movw sec, %cx /* get sector number */ + movw head, %dx /* get head number */ + movb drive, %dl + + movw $BD_READ1, %ax /* read 1 sector */ + int $BIOS_DISK + jnc readcont /* jmp if it worked ok */ + + movw $err_diskread, %si /* report the error */ + call dispMsg + popw %cx /* get the retry count back */ + loop retry /* and go try again. */ + movw $err_diskfail, %si /* can't proceed, */ + call dispMsg /* print message and freeze. */ + jmp . + +readcont: + movw $msg_dot, %si /* print status: a dot */ + call dispMsg + cmpw $OFFSET_LIMIT, %bx /* have we reached the offset limit? */ + je adjust /* Yes--must adjust the es register */ + addw $SECTOR_SIZE, %bx /* No--just adjust the block size to */ + jmp readcont2 /* the offset and continue. */ + +adjust: + movw $0, %bx /* start offset over again */ + movw %es, %ax + addw $0x1000,%ax /* move segment pointer to next chunk */ + movw %ax, %es + +readcont2: + incb %cl /* not done - move to the next sector */ + cmpb max_sec, %cl /* see if we need */ + jnz save_sector /* to switch heads or tracks */ + + movb $1, %cl /* reset sector number */ + incb %dh /* first, switch heads */ + cmpb max_head, %dh /* there are only two - if we've already */ + jnz save_sector /* used both, we need to switch tracks */ + + xorb %dh, %dh /* reset to head 0 */ + incb %ch /* inc track number */ + cmpb $80, %ch /* 80 tracks per side - have we read all? */ + jnz save_sector /* read another track */ + + movw $err_toobig, %si /* report the error */ + call dispMsg + jmp . /* and freeze */ + +save_sector: + movw %cx, sec /* save sector number */ + movw %dx, head /* and head number */ + + popw %ax /* discard the retry count */ + popw %ax /* get the sector count from the stack */ + decw %ax /* and decrement it. */ + jg readprog /* If it is zero, we're done reading. */ + +readdone: + movw $msg_bar, %si /* print message saying this block is done */ + call dispMsg + ret /* and return to the caller */ + +/* +** We've loaded the whole target program into memory, +** so it's time to transfer to the startup code. +*/ +done_loading: + movw $msg_go, %si /* last status message */ + call dispMsg + + jmp switch /* move to the next phase */ + +/* +** Support routine - display a message byte by byte to the monitor. +*/ +dispMsg: + pushw %ax + pushw %bx +repeat: + lodsb /* grab next character */ + + movb $BV_W_ADV, %ah /* write and advance cursor */ + movw $0x07, %bx /* page 0, white on blank, no blink */ + orb %al, %al /* AL is character to write */ + jz getOut /* if we've reached the NUL, get out */ + + int $BIOS_VIDEO /* otherwise, print and repeat */ + jmp repeat + +getOut: /* we're done, so return */ + popw %bx + popw %ax + ret + +/* +** Support routine - move the GDT entries from where they are to +** location 0050:0000. We need to add BOOT_ADDR because the bootstrap +** is linked at 0, but loaded at 0x7c00. +*/ +move_gdt: + movw %cs, %si + movw %si, %ds + movw $start_gdt + BOOT_ADDR, %si + movw $GDT_SEG, %di + movw %di, %es + xorw %di, %di + movl $gdt_len, %ecx + cld + rep movsb + ret + +/* +** DATA AREAS. +** +** Next sector number and head number to read from. +*/ +sec: .word 2 /* cylinder=0, sector=1 */ +head: .word 0 /* head=0 */ +max_sec: .byte 19 /* up to 18 sectors per floppy track */ +max_head: .byte 2 /* only two r/w heads per floppy drive */ + +/* +** Status and error messages. +*/ +msg_loading: .asciz "Loading" +msg_dot: .asciz "." +msg_go: .asciz "done." +msg_bar: .asciz "|" + +/* +** Error messages. +*/ +err_diskstatus: .asciz "Disk not ready.\n\r" +err_diskread: .asciz "Read failed\n\r" +err_toobig: .asciz "Too big\n\r" +err_diskfail: .asciz "Can't proceed\n\r" + +/* +** Data areas. +*/ + +/* +** The GDTR and IDTR contents. +*/ +gdt_48: + .word 0x2000 /* 1024 GDT entries x 8 bytes/entry = 8192 */ + .quad GDT_ADDR + +idt_48: + .word 0x0800 /* 256 interrupts */ + .quad IDT_ADDR + +/* +** Depending on the age of the BIOS, it may expect there to be a +** partition table for the hard drive you're booting from at this point +** in the boot sector; only the first 446 bytes (0x000-0x1bd) can be +** used for bootstrap code/data. To make life easy, we'll just skip +** over the rest of the sector. +** +** Note: when booting from floppy, this isn't a problem, because floppy +** disks don't have partition tables. On some machines, USB-type storage +** devices are treated as floppies, so they also don't have partition +** maps; however, on other systems, USB storage is treated as hard disk +** storage. +*/ + +/* +** End of the first sector of the boot program. The last two bytes +** of this sector must be AA55 in order for the disk to be recognized +** by the BIOS as bootable. +*/ + .org SECTOR_SIZE-4 + +drive: .word BDEV /* 0x00 = floppy, 0x80 = usb */ + +boot_sig: + .word 0xAA55 + +/******************************************************* +******* BEGINNING OF SECTOR TWO OF THE BOOTSTRAP ******* +*******************************************************/ + +/* +** This code configures the GDT, enters protected mode, and then +** transfers to the OS entry point. +*/ + +switch: + cli + movb $NMI_DISABLE, %al /* also disable NMIs */ + outb %al, $CMOS_ADDR + +#ifdef USE_FLOPPY + call floppy_off +#endif + call enable_A20 + call move_gdt +#ifdef GET_MMAP + call check_memory +#endif + +/* +** Get the memory address for the "user blob" out of the table +** at the end of this sector, and pass the three values to the +** protected mode code in %bx, %cx, and %dx. We could figure out +** how to find it from there, but this is easier. +*/ +# movw u_off+BOOT_ADDR, %bx +# movw u_seg+BOOT_ADDR, %cx +# movw u_sect+BOOT_ADDR, %dx + +/* +** The IDTR and GDTR are loaded relative to this segment, so we must +** use the full offsets from the beginning of the segment (0000:0000); +** however, we were loaded at 0000:7c00, so we need to add that in. +*/ + lidt idt_48 + BOOT_ADDR + lgdt gdt_48 + BOOT_ADDR + + movl %cr0, %eax /* get current CR0 */ + orl $1, %eax /* set the PE bit */ + movl %eax, %cr0 /* and store it back. */ + + /* + ** We'll be in protected mode at the start of the user's code + ** right after this jump executes. + ** + ** First, a byte to force 32-bit mode execution, followed by + ** a 32-bit long jump. The long ("far") jump loads both EIP + ** and CS with the proper values so that when we land at the + ** destination address in protected mode, the next instruction + ** fetch doesn't cause a fault. + ** + ** The old code for this: + ** + ** .byte 0x66, 0xEA + ** .long TARGET_ADDR + ** .word GDT_CODE + */ + + .byte 0x66 + .code32 + ljmp $GDT_CODE, $TARGET_ADDR + .code16 + +/* +** Supporting functions. +*/ + +#ifdef USE_FLOPPY +/* +** Turn off the motor on the floppy disk drive. +*/ +floppy_off: + push %dx + movw $0x3f2, %dx + xorb %al, %al + outb %al, %dx + pop %dx + ret +#endif + +/* +** Enable the A20 gate for full memory access. +*/ +enable_A20: + call a20wait + movb $KBD_P1_DISABLE, %al + outb %al, $KBD_CMD + + call a20wait + movb $KBD_RD_OPORT, %al + outb %al, $KBD_CMD + + call a20wait2 + inb $KBD_DATA, %al + pushl %eax + + call a20wait + movb $KBD_WT_OPORT, %al + outb %al, $KBD_CMD + + call a20wait + popl %eax + orb $2, %al + outb %al, $KBD_DATA + + call a20wait + mov $KBD_P1_ENABLE, %al + out %al, $KBD_CMD + + call a20wait + ret + +a20wait: /* wait until bit 1 of the device register is clear */ + movl $65536, %ecx /* loop a lot if need be */ +wait_loop: + inb $KBD_STAT, %al /* grab the byte */ + test $2, %al /* is the bit clear? */ + jz wait_exit /* yes */ + loop wait_loop /* no, so loop */ + jmp a20wait /* if still not clear, go again */ +wait_exit: + ret + +a20wait2: /* like a20wait, but waits until bit 0 is set. */ + mov $65536, %ecx +wait2_loop: + in $KBD_STAT, %al + test $1, %al + jnz wait2_exit + loop wait2_loop + jmp a20wait2 +wait2_exit: + ret + +#ifdef GET_MMAP +/* +** Query the BIOS to get the list of usable memory regions +** +** Adapted from: http://wiki.osdev.org/Detecting_Memory_%28x86%29 +** (see section "BIOS Function INT 0x15. EAX = 0xE820") +** +** After the first 'int', if the location 0x2D00 (4 bytes) contains -1, +** then this method failed to detect memory properly; otherwise, this +** location contains the number of elements read. +** +** The start of the array is at 0x2D04. The elements are tightly +** packed following the layout as defined below. Each entry in the +** array contains the following information: +** +** uint64_t base address of region +** uint64_t length of region (0 --> ignore the entry) +** uint32_t type of region +** uint32_t ACIP 3.0 Extended Attributes +** +** The C struct definition is as follows: +** +** struct MemMapEntry +** { +** uint32_t base[2]; // 64-bit base address +** uint32_t length[2]; // 64-bit length +** uint32_t type; // 32-bit region type +** uint32_t ACPI; // 32-bit ACPI "extended attributes" bitfield +** }; +** +** This structure must be packed in memory. This shouldn't be a problem, +** but if it is, you may need to add this attribute at the end of the +** struct declaration before the semicolon: +** +** __attribute__((packed)) +** +** Parameters: +** None +**/ +check_memory: + // save everything + // pushaw won't work here because we're still in real mode + pushw %ds + pushw %es + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + + // Set the start of the buffer + movw $MMAP_SEG, %bx // 0x2D0 + mov %bx, %ds // Data segment now starts at 0x2D00 + mov %bx, %es // Extended segment also starts at 0x2D00 + + // Reserve the first 4 bytes for the # of entries + movw $0x4, %di + // Make a valid ACPI 3.X entry + movw $1, %es:20(%di) + + xorw %bp, %bp // Count of entries in the list + xorl %ebx, %ebx // EBX must contain zeroes + + movl $MMAP_MAGIC_NUM, %edx // Magic number into EDX + movl $MMAP_CODE, %eax // E820 memory command + movl $MMAP_ENT, %ecx // Ask the BIOS for 24 bytes + int $BIOS_MISC // Call the BIOS + + // check for success + jc cm_failed // C == 1 --> failure + movl $MMAP_MAGIC_NUM, %edx // sometimes EDX changes + cmpl %eax, %edx // EAX should equal EDX after the call + jne cm_failed + testl %ebx, %ebx // Should have at least one more entry + je cm_failed + + jmp cm_jumpin // Good to go - start us off + +cm_loop: + movl $MMAP_CODE, %eax // Reset our registers + movw $1, 20(%di) + movl $MMAP_ENT, %ecx + int $BIOS_MISC + jc cm_end_of_list // C == 1 --> end of list + movl $MMAP_MAGIC_NUM, %edx + +cm_jumpin: + jcxz cm_skip_entry // Did we get any data? + + cmp $20, %cl // Check the byte count + jbe cm_no_text // Skip the next test if only 20 bytes + + testb $1, %es:20(%di) // Check the "ignore this entry" flag + je cm_skip_entry + +cm_no_text: + mov %es:8(%di), %ecx // lower half of length + or %es:12(%di), %ecx // now, full length + jz cm_skip_entry + + inc %bp // one more valid entry + + // make sure we don't overflow our space + cmpw $MMAP_MAX_ENTS, %bp + jge cm_end_of_list + + // we're ok - move the pointer to the next struct in the array + add $24, %di + +cm_skip_entry: + // are there more entries to retrieve? + testl %ebx, %ebx + jne cm_loop + +cm_end_of_list: + // All done! Store the number of elements in 0x2D00 + movw %bp, %ds:0x0 + + clc // Clear the carry bit and return + jmp cm_ret + +cm_failed: + movl $-1, %ds:0x0 // indicate failure + stc + +cm_ret: + // restore everything we saved + // popaw won't work here (still in real mode!) + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + popw %es + popw %ds + ret +#endif + +/* +** The GDT. This cannot be created in C because the bootstrap is not +** linked with that code. We could just have a simple "dummy" GDT here +** but that would only save us a couple of entries. Also, we could save +** some space by not having the separate 'linear' and 'stack' entries +** (they're identical to the 'data' entry). +*/ + .p2align 2 // force 4-byte alignment +start_gdt: + // selector 0x0000 is unused + SEGNULL + + // selector 0x0008 - basic linear access to all of memory + SEGMENT( 0x0, 0xffffffff, SEG_DPL_0, SEG_DATA_RW ) + + // selector 0x0010 - kernel code segment + SEGMENT( 0x0, 0xffffffff, SEG_DPL_0, SEG_CODE_XR ) + + // selector 0x0018 - kernel data segment + SEGMENT( 0x0, 0xffffffff, SEG_DPL_0, SEG_DATA_RW ) + + // selector 0x0020 - kernel stack segment + SEGMENT( 0x0, 0xffffffff, SEG_DPL_0, SEG_DATA_RW ) + + // could put additional entries here for user mode - e.g., + // 0x0028 code: SEGMENT( 0x0, 0xffffffff, SEG_DPL_3, SEG_CODE_XR ) + // 0x0030 data: SEGMENT( 0x0, 0xffffffff, SEG_DPL_3, SEG_DATA_RW ) + // 0x0038 stack: SEGMENT( 0x0, 0xffffffff, SEG_DPL_3, SEG_DATA_RW ) + +end_gdt: +gdt_len = end_gdt - start_gdt + +/* +** The end of this program will contain a list of the sizes and load +** addresses of all of the blocks to be loaded. These values are +** inserted here by the BuildImage program, which checks that there are +** not so many blocks that the GDT would be overwritten. The layout +** of the data is: +** +** struct info_s { +** short offset; +** short segment; +** short sectors; +** }; +** +** with the data for the first program at k_off, k_seg, and k_sect. +** If additional blocks are to be loaded, their values appear just +** before the previous set. +*/ + + .org BOOT_SIZE-12 +u_off: .word 0 // the "user blob" +u_seg: .word 0 +u_sect: .word 0 +k_off: .word 0 // the kernel +k_seg: .word 0 +k_sect: .word 0 diff --git a/doc/Memory.txt b/doc/Memory.txt new file mode 100644 index 0000000..cecfea3 --- /dev/null +++ b/doc/Memory.txt @@ -0,0 +1,92 @@ +Systems Programming framework memory layout + +Version: @(#)Memory.txt 2.2a +Date: 3/23/25 +--------------------------------------------------------------------------- + +This diagram shows important areas in the first 1MB of memory as seen +by the standalone framework code. + +Each row in the diagram represents 0x100 (256) bytes of memory, except in +"elided" areas (< ... >). The starting address is indicated for each +region in hex; if a CPP #define exists for that region in either +bootstrap.h or x86/bios.h, its name is also given. + + ----------------------- + | Interrupt Vector | 0x00000 + | 256 x 4 bytes | + | (1024, 0x400) | + | | + ----------------------- + | BIOS Data Area (BDA)| 0x00400 BIOS_BDA + ----------------------- + | GDT | 0x00500 GDT_ADDR + | 1024 x 8 bytes | + | (8192, 0x2000) | + | | + < . . . > + | | + ----------------------- + | IDT | 0x02500 IDT_ADDR + | 256 x 8 bytes | + | (2048, 0x800) | + | | + | | + | | + | | + | | + ----------------------- + | Mmap data | 0x02D00 MMAP_ADDR + | | + | | + | | + | | + < . . . > + | | + ----------------------- + | Bootstrap sector 1 | 0x07c00 BOOT_ADDR + | | + ----------------------- + | Bootstrap sector 2 | 0x07e00 PART2_ADDR + | | + ----------------------- + | | 0x08000 + | | + < . . . > + | ^ | + | Bootstrap stack | | + ----------------------- + | | 0x0bc00 BOOT_SP_ADDR + | | + | | + < . . . > + | OS stack | + ----------------------- + | Operating System | 0x10000 TARGET_ADDR, TARGET_STACK + | (size varies) | + | | + < . . . > + | | + ----------------------- + | User Code Blob | 0x30000 + | (size varies) | + | | + < . . . > + | | + ----------------------- + | Extended BIOS Data | 0x9fc00 + | Area (EBDA) | + | | + < . . . > + | | + ----------------------- + | Video memory | 0xb8000 VID_BASE_ADDR + | | + < . . . > + | | + ----------------------- + | The BIOS | 0xf0000 + | | + < . . . > + | | + ----------------------- 0xfffff diff --git a/doc/NOTES b/doc/NOTES new file mode 100644 index 0000000..0d05ca2 --- /dev/null +++ b/doc/NOTES @@ -0,0 +1,162 @@ +Systems Programming standalone framework information + +Version: @(#)NOTES 2.3 +Date: 12/4/23 +--------------------------------------------------------------------------- + +Notes on the Makefile: + + DO NOT USE gmakemake! You must edit the given Makefile to tell + it about the file(s) you create. Add your own file names (both + source and object versions) to the APP_* macros at the top of the + Makefile. + + After adding or removing files from the Makefile (or changing + your #includes), do a "make depend" to adjust the Makefile's + dependency entries. + +To create your program: + + * run 'make' in your project directory + +To copy it onto a USB flash drive: + + All machines in the DSL have at least two front-panel USB slots + (typically, two USB-2 and one blue USB-3). Under Ubuntu, you + can use any of these slots; insert a flash drive, and the OS + automatically creates device entries for the drive, using the + next available disk name in /dev (e.g., /dev/sdg). + + To copy your bootable image to the flash drive, plug the drive + into a USB socket, wait a few moments for Ubuntu to recognize + it and create the device entries in /dev, and type + + make usb + + This will remake the disk.img file (if necessary), and will then + copy it out to the USB drive. In order to find the correct + drive, the installation uses a local command named 'dcopy'. This + command runs a second command named 'dfind' to identify the USB + drive(s) plugged into the system, and then runs a 'dd' command + to copy the disk.img file to the first USB device it finds. + (You can run 'dfind' yourself if you want to be sure that 'dcopy' + will be able to find the flash drive.) + + Note: the Makefile still has a "floppy" target for creating a + bootable floppy disk image. However, this hasn't been used for + quite a while, and the necessary support tools to do the copying + don't exist on the current systems. If you want to try using the + floppy disk as a boot device, let me know. + +To boot your program once you have copied it to a bootable medium: + + * DO NOT USE the machine named 'sherlock' - it's a server for + the lab, and should not be shut down + * shut down Ubuntu by using the standard Ubuntu "shut down" + menu entry + * insert the bootable medium + * make sure the terminal connected to this machine is turned on + * push the reset button on the front panel (at the top, on + the righthand side - the larger button on the lefthand + side is the power button) + + DO NOT just push the reset button - Ubuntu must be shut down + correctly in order to avoid damaging the filesystems. + + Unfortunately, the motherboards in the current lab machines are + somewhat stupid; once a flash drive is unplugged, they forget + that we want to give boot priority to flash drives once the + flash drive is unplugged. For now, you will need to interrupt + the boot process in one of the following two ways: + + 1. When the ASUS logo appears on the screen, press the + F8 key to bring up the boot device screen. Scroll + down the list using the arrow keys until the flash + drive is highlighted, and press ENTER to boot from it. + + 2. When the ASUS log appears on the screen, press either + the F2 or the DEL key on the keyboard to bring up the + BIOS screen. Use the right arrow key to select the + "Boot" menu, then the down arrow key to the bottom of + the "Boot" menu, where you will find an "Override" + section. Select the flash drive entry and press + ENTER. + + If you miss your window of opportunity (about five seconds) + to press one of these function keys and Ubuntu boots up, don't + panic; just shut Ubuntu down and try again. + + If you want to run your program again, leave the flash drive + inserted and press the reset button again. + +To reboot Ubuntu: + + * take your bootable medium out of the machine + * push the reset button + +Compiling your program creates several files: + + prog.o: linked, object form of the system + + prog.b: binary version of the system - generated from prog.o + by removing all the object file headers and symbol table + + prog.nl: namelist of the prog.o file - lists all global symbols, + their values, and the program section they're defined in + (Text, Data, Bss) + + *.img: the binary system image - contains the bootstrap, the + protected mode startup code, and your stuff, in this layout: + + bootstrap first sector + switch code second sector + your program sectors 3 through n+2 + next file n+3 through p+n+2 + next file p+n+3 through q+p+n+2 + etc. (see below) + + This file will be named floppy.img or disk.img, + depending on which device you'll be using. + + BuildImage: is used to patch the system length into the boot + sector of the *.img file + + Offsets: prints byte offsets for major structures (only present + in distributions of the baseline OS written by the class + in Systems Programming) + +Other things you can 'make': + + prog.dis: a disassembly of the prog.o file - a text version of + the binary machine code + + prog.nll: like prog.nl, but includes non-global symbols as well + as globals (e.g., static local variables in files) + + file.X: generates an assembly listing from the C source file + named "file.c" which has the C source code inserted around + the assembly code + + clean: deletes all object, listing, and binary files + + depend: recreates the dependency lists in the Makefile + +Loading additional files: + + You can load additional files into memory by adding the name of + the file and the address where you want it loaded to the end of + the BuildImage command in the Makefile. However, because the + loading is done in real mode, you cannot load into addresses + above 0x9ffff. See the code in BuildImage.c for more details. + +Modifying the bootstrap: + + You can add some code to the bootstrap without significantly + changing its size. The baseline bootstrap assembles to 0x2ad + bytes without the memory map code, or 0x353 with that code; this + leaves about 330 (or 170) bytes available at the end of the second + sector. If you need to add more than will fit there, you will + need to change the definition of BOOT_SIZE at the beginning of + the file, the code which loads the second half of the bootstrap + from the device, and the ".org" at the end of the file to reflect + the new length of the bootstrap. diff --git a/doc/user_image.txt b/doc/user_image.txt new file mode 100644 index 0000000..9527e12 --- /dev/null +++ b/doc/user_image.txt @@ -0,0 +1,5841 @@ +Partial disassembly of user.img, 2025/03/22 + +Blob header: +00000000 42 4c 42 00 14 00 00 00 |BLB.....| "BLB", 00000014 entries + +Program table [0]: +00000000 69 6e 69 74 00 00 00 00 |init....| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 88 02 00 00 |................| offset 00000288 +00000020 68 17 00 00 00 00 00 00 |h.......| + +Program table [1]: +00000020 69 64 6c 65 00 00 00 00 |idle....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 f0 19 00 00 |................| offset 000019f0 +00000040 78 16 00 00 00 00 00 00 |x.......| + +Program table [2] - [19]: +00000040 73 68 65 6c 6c 00 00 00 |shell...| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 68 30 00 00 |............h0..| +00000060 34 1b 00 00 01 00 00 00 70 72 6f 67 41 42 43 00 |4.......progABC.| +00000070 00 00 00 00 00 00 00 00 00 00 00 00 a0 4b 00 00 |.............K..| +00000080 ac 16 00 00 01 00 00 00 70 72 6f 67 44 45 00 00 |........progDE..| +00000090 00 00 00 00 00 00 00 00 00 00 00 00 50 62 00 00 |............Pb..| +000000a0 ac 16 00 00 01 00 00 00 70 72 6f 67 46 47 00 00 |........progFG..| +000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 79 00 00 |.............y..| +000000c0 ac 16 00 00 01 00 00 00 70 72 6f 67 48 00 00 00 |........progH...| +000000d0 00 00 00 00 00 00 00 00 00 00 00 00 b0 8f 00 00 |................| +000000e0 ac 16 00 00 01 00 00 00 70 72 6f 67 49 00 00 00 |........progI...| +000000f0 00 00 00 00 00 00 00 00 00 00 00 00 60 a6 00 00 |............`...| +00000100 ac 16 00 00 01 00 00 00 70 72 6f 67 4a 00 00 00 |........progJ...| +00000110 00 00 00 00 00 00 00 00 00 00 00 00 10 bd 00 00 |................| +00000120 ac 16 00 00 01 00 00 00 70 72 6f 67 4b 4c 00 00 |........progKL..| +00000130 00 00 00 00 00 00 00 00 00 00 00 00 c0 d3 00 00 |................| +00000140 ac 16 00 00 01 00 00 00 70 72 6f 67 4d 4e 00 00 |........progMN..| +00000150 00 00 00 00 00 00 00 00 00 00 00 00 70 ea 00 00 |............p...| +00000160 ac 16 00 00 01 00 00 00 70 72 6f 67 50 00 00 00 |........progP...| +00000170 00 00 00 00 00 00 00 00 00 00 00 00 20 01 01 00 |............ ...| +00000180 ac 16 00 00 01 00 00 00 70 72 6f 67 51 00 00 00 |........progQ...| +00000190 00 00 00 00 00 00 00 00 00 00 00 00 d0 17 01 00 |................| +000001a0 78 16 00 00 00 00 00 00 70 72 6f 67 52 00 00 00 |x.......progR...| +000001b0 00 00 00 00 00 00 00 00 00 00 00 00 48 2e 01 00 |............H...| +000001c0 ac 16 00 00 01 00 00 00 70 72 6f 67 53 00 00 00 |........progS...| +000001d0 00 00 00 00 00 00 00 00 00 00 00 00 f8 44 01 00 |.............D..| +000001e0 ac 16 00 00 01 00 00 00 70 72 6f 67 54 55 56 00 |........progTUV.| +000001f0 00 00 00 00 00 00 00 00 00 00 00 00 a8 5b 01 00 |.............[..| +00000200 ac 16 00 00 01 00 00 00 70 72 6f 67 57 00 00 00 |........progW...| +00000210 00 00 00 00 00 00 00 00 00 00 00 00 58 72 01 00 |............Xr..| +00000220 ac 16 00 00 01 00 00 00 70 72 6f 67 58 00 00 00 |........progX...| +00000230 00 00 00 00 00 00 00 00 00 00 00 00 08 89 01 00 |................| +00000240 ac 16 00 00 01 00 00 00 70 72 6f 67 59 00 00 00 |........progY...| +00000250 00 00 00 00 00 00 00 00 00 00 00 00 b8 9f 01 00 |................| +00000260 ac 16 00 00 01 00 00 00 70 72 6f 67 5a 00 00 00 |........progZ...| +00000270 00 00 00 00 00 00 00 00 00 00 00 00 68 b6 01 00 |............h...| +00000280 ac 16 00 00 01 00 00 00 |........| + +Program #0 ELF file: +00000280 7f 45 4c 46 01 01 01 00 |.ELF....| <-- init @ 00000288 +00000290 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 |................| +000002a0 49 14 00 00 34 00 00 00 28 16 00 00 00 00 00 00 |I...4...(.......| +000002b0 34 00 20 00 02 00 28 00 08 00 07 00 01 00 00 00 |4. ...(.........| +000002c0 80 00 00 00 00 10 00 00 00 10 00 00 9d 10 00 00 |................| +000002d0 00 20 00 00 07 00 00 00 20 00 00 00 51 e5 74 64 |. ...... ...Q.td| +000002e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000002f0 00 00 00 00 07 00 00 00 10 00 00 00 00 00 00 00 |................| +00000300 00 00 00 00 00 00 00 00 55 89 e5 81 ec 98 00 00 |........U.......| +00000310 00 e8 d5 03 00 00 89 45 f4 83 7d f4 00 79 34 8b |.......E..}..y4.| +00000320 45 08 8b 00 83 ec 04 50 68 39 1a 00 00 8d 85 74 |E......Ph9.....t| +00000330 ff ff ff 50 e8 28 04 00 00 83 c4 10 83 ec 0c 8d |...P.(..........| +00000340 85 74 ff ff ff 50 e8 df 02 00 00 83 c4 10 e9 84 |.t...P..........| +00000350 00 00 00 83 7d f4 00 75 5f 8b 45 08 0f b6 40 08 |....}..u_.E...@.| +00000360 0f b6 c0 83 ec 0c 50 e8 bf 03 00 00 83 c4 10 8b |......P.........| +00000370 45 08 8d 50 0c 8b 45 08 8b 00 83 ec 08 52 50 e8 |E..P..E......RP.| +00000380 6f 03 00 00 83 c4 10 8b 45 08 8b 00 83 ec 04 50 |o.......E......P| +00000390 68 54 1a 00 00 8d 85 74 ff ff ff 50 e8 c0 03 00 |hT.....t...P....| +000003a0 00 83 c4 10 83 ec 0c 8d 85 74 ff ff ff 50 e8 77 |.........t...P.w| +000003b0 02 00 00 83 c4 10 eb 1f 0f b6 05 9c 20 00 00 0f |............ ...| +000003c0 be c0 83 ec 0c 50 e8 a7 02 00 00 83 c4 10 8b 55 |.....P.........U| +000003d0 f4 8b 45 08 89 50 04 90 c9 c3 8d 4c 24 04 83 e4 |..E..P.....L$...| +000003e0 f0 ff 71 fc 55 89 e5 51 81 ec a4 00 00 00 89 c8 |..q.U..Q........| +000003f0 83 38 01 7e 2d 8b 50 04 83 c2 04 8b 12 0f b6 12 |.8.~-.P.........| +00000400 0f be d2 89 55 ec 83 7d ec 20 76 16 83 7d ec 7e |....U..}. v..}.~| +00000410 77 10 8b 40 04 83 c0 04 8b 00 0f b6 00 a2 9c 20 |w..@........... | +00000420 00 00 83 ec 0c 68 6f 1a 00 00 e8 fb 01 00 00 83 |.....ho.........| +00000430 c4 10 83 ec 0c 6a 1a e8 36 02 00 00 83 c4 10 c7 |.....j..6.......| +00000440 45 f4 00 00 00 00 eb 04 83 45 f4 01 81 7d f4 9f |E........E...}..| +00000450 25 26 00 7e f3 83 ec 0c 68 80 1a 00 00 e8 31 02 |%&.~....h.....1.| +00000460 00 00 83 c4 10 83 ec 0c 68 a8 1a 00 00 e8 b8 01 |........h.......| +00000470 00 00 83 c4 10 c7 45 f0 00 20 00 00 eb 12 83 ec |......E.. ......| +00000480 0c ff 75 f0 e8 7f fe ff ff 83 c4 10 83 45 f0 34 |..u..........E.4| +00000490 8b 45 f0 8b 00 3d 62 60 01 00 75 e2 83 ec 0c 68 |.E...=b`..u....h| +000004a0 c7 1a 00 00 e8 ea 01 00 00 83 c4 10 83 ec 0c 68 |...............h| +000004b0 d0 1a 00 00 e8 71 01 00 00 83 c4 10 83 ec 08 8d |.....q..........| +000004c0 85 64 ff ff ff 50 6a 00 e8 16 02 00 00 83 c4 10 |.d...Pj.........| +000004d0 89 45 e8 83 7d e8 00 7f 2e 83 ec 04 ff 75 e8 68 |.E..}........u.h| +000004e0 f4 1a 00 00 8d 85 68 ff ff ff 50 e8 71 02 00 00 |......h...P.q...| +000004f0 83 c4 10 83 ec 0c 8d 85 68 ff ff ff 50 e8 28 01 |........h...P.(.| +00000500 00 00 83 c4 10 eb b5 8b 85 64 ff ff ff 50 ff 75 |.........d...P.u| +00000510 e8 68 14 1b 00 00 8d 85 68 ff ff ff 50 e8 3f 02 |.h......h...P.?.| +00000520 00 00 83 c4 10 83 ec 0c 8d 85 68 ff ff ff 50 e8 |..........h...P.| +00000530 f6 00 00 00 83 c4 10 c7 45 f0 00 20 00 00 eb 2b |........E.. ...+| +00000540 8b 45 f0 8b 50 04 8b 45 e8 39 c2 75 1a 8b 45 f0 |.E..P..E.9.u..E.| +00000550 c7 40 04 00 00 00 00 83 ec 0c ff 75 f0 e8 a6 fd |.@.........u....| +00000560 ff ff 83 c4 10 eb 10 83 45 f0 34 8b 45 f0 8b 00 |........E.4.E...| +00000570 3d 62 60 01 00 75 c9 e9 40 ff ff ff 55 89 e5 83 |=b`..u..@...U...| +00000580 ec 08 83 ec 08 ff 75 08 6a 00 e8 54 01 00 00 83 |......u.j..T....| +00000590 c4 10 c9 c3 55 89 e5 81 ec 18 01 00 00 e8 49 01 |....U.........I.| +000005a0 00 00 89 45 f4 83 7d f4 00 74 05 8b 45 f4 eb 57 |...E..}..t..E..W| +000005b0 e8 56 01 00 00 89 45 f4 83 ec 08 ff 75 0c ff 75 |.V....E.....u..u| +000005c0 08 e8 2d 01 00 00 83 c4 10 ff 75 08 ff 75 f4 68 |..-.......u..u.h| +000005d0 2b 1b 00 00 8d 85 f4 fe ff ff 50 e8 81 01 00 00 |+.........P.....| +000005e0 83 c4 10 83 ec 0c 8d 85 f4 fe ff ff 50 e8 38 00 |............P.8.| +000005f0 00 00 83 c4 10 83 ec 0c 6a ff e8 dc 00 00 00 83 |........j.......| +00000600 c4 10 b8 00 00 00 00 c9 c3 55 89 e5 83 ec 18 8b |.........U......| +00000610 45 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 00 |E..E....j..E.Pj.| +00000620 e8 de 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 |..........U.....| +00000630 83 ec 0c ff 75 08 e8 9b 03 00 00 83 c4 10 89 45 |....u..........E| +00000640 f4 8b 45 f4 83 ec 04 50 ff 75 08 6a 00 e8 b1 00 |..E....P.u.j....| +00000650 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 |.......U........| +00000660 ff 75 0c ff 75 08 6a 00 e8 96 00 00 00 83 c4 10 |.u..u.j.........| +00000670 c9 c3 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec |..U......E..E...| +00000680 04 6a 01 8d 45 f4 50 6a 01 e8 75 00 00 00 83 c4 |.j..E.Pj..u.....| +00000690 10 c9 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 |...U.........u..| +000006a0 32 03 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 |2.......E..E....| +000006b0 50 ff 75 08 6a 01 e8 48 00 00 00 83 c4 10 c9 c3 |P.u.j..H........| +000006c0 55 89 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a |U.........u..u.j| +000006d0 01 e8 2d 00 00 00 83 c4 10 c9 c3 b8 00 00 00 00 |..-.............| +000006e0 cd 80 c3 b8 01 00 00 00 cd 80 c3 b8 02 00 00 00 |................| +000006f0 cd 80 c3 b8 03 00 00 00 cd 80 c3 b8 04 00 00 00 |................| +00000700 cd 80 c3 b8 05 00 00 00 cd 80 c3 b8 06 00 00 00 |................| +00000710 cd 80 c3 b8 07 00 00 00 cd 80 c3 b8 08 00 00 00 |................| +00000720 cd 80 c3 b8 09 00 00 00 cd 80 c3 b8 0a 00 00 00 |................| +00000730 cd 80 c3 b8 0b 00 00 00 cd 80 c3 b8 0c 00 00 00 |................| +00000740 cd 80 c3 b8 ad 0b 00 00 cd 80 c3 50 e8 8a ff ff |...........P....| +00000750 ff e8 84 fc ff ff 83 ec 0c 50 e8 7c ff ff ff eb |.........P.|....| +00000760 fe 55 89 e5 83 ec 38 8d 45 0c 83 c0 04 89 45 f4 |.U....8.E.....E.| +00000770 e9 3f 02 00 00 80 7d f3 25 0f 85 26 02 00 00 c7 |.?....}.%..&....| +00000780 45 ec 00 00 00 00 c7 45 e4 20 00 00 00 c7 45 e8 |E......E. ....E.| +00000790 00 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |.....E..P..U....| +000007a0 88 45 f3 80 7d f3 2d 75 16 c7 45 ec 01 00 00 00 |.E..}.-u..E.....| +000007b0 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 |.E..P..U.....E..| +000007c0 7d f3 30 75 40 c7 45 e4 30 00 00 00 8b 45 0c 8d |}.0u@.E.0....E..| +000007d0 50 01 89 55 0c 0f b6 00 88 45 f3 eb 28 8b 55 e8 |P..U.....E..(.U.| +000007e0 89 d0 c1 e0 02 01 d0 01 c0 89 45 e8 0f be 45 f3 |..........E...E.| +000007f0 83 e8 30 01 45 e8 8b 45 0c 8d 50 01 89 55 0c 0f |..0.E..E..P..U..| +00000800 b6 00 88 45 f3 80 7d f3 2f 7e 06 80 7d f3 39 7e |...E..}./~..}.9~| +00000810 cc 0f be 45 f3 83 e8 63 83 f8 15 0f 87 93 01 00 |...E...c........| +00000820 00 8b 04 85 48 1b 00 00 ff e0 8b 45 f4 8d 50 04 |....H......E..P.| +00000830 89 55 f4 8b 00 88 45 f3 0f b6 45 f3 88 45 d0 c6 |.U....E...E..E..| +00000840 45 d1 00 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a |E......u..u..u.j| +00000850 01 8d 45 d0 50 ff 75 08 e8 17 04 00 00 83 c4 20 |..E.P.u........ | +00000860 89 45 08 e9 4c 01 00 00 8b 45 f4 8d 50 04 89 55 |.E..L....E..P..U| +00000870 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 78 01 00 00 |......P.E.P.x...| +00000880 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff |....E.....u..u..| +00000890 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 d3 03 00 |u..u..E.P.u.....| +000008a0 00 83 c4 20 89 45 08 e9 08 01 00 00 8b 45 f4 8d |... .E.......E..| +000008b0 50 04 89 55 f4 8b 00 89 45 dc 83 ec 08 ff 75 e4 |P..U....E.....u.| +000008c0 ff 75 ec ff 75 e8 6a ff ff 75 dc ff 75 08 e8 a1 |.u..u.j..u..u...| +000008d0 03 00 00 83 c4 20 89 45 08 e9 d6 00 00 00 8b 45 |..... .E.......E| +000008e0 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 |..P..U......P.E.| +000008f0 50 e8 d2 01 00 00 83 c4 10 89 45 e0 83 ec 08 ff |P.........E.....| +00000900 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff |u..u..u..u..E.P.| +00000910 75 08 e8 5d 03 00 00 83 c4 20 89 45 08 e9 92 00 |u..]..... .E....| +00000920 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 |...E..P..U......| +00000930 50 8d 45 d0 50 e8 18 02 00 00 83 c4 10 89 45 e0 |P.E.P.........E.| +00000940 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d |....u..u..u..u..| +00000950 45 d0 50 ff 75 08 e8 19 03 00 00 83 c4 20 89 45 |E.P.u........ .E| +00000960 08 eb 51 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec |..Q.E..P..U.....| +00000970 08 50 8d 45 d0 50 e8 61 02 00 00 83 c4 10 89 45 |.P.E.P.a.......E| +00000980 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 |.....u..u..u..u.| +00000990 8d 45 d0 50 ff 75 08 e8 d8 02 00 00 83 c4 20 89 |.E.P.u........ .| +000009a0 45 08 90 eb 0f 8b 45 08 8d 50 01 89 55 08 0f b6 |E.....E..P..U...| +000009b0 55 f3 88 10 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |U....E..P..U....| +000009c0 88 45 f3 80 7d f3 00 0f 85 a8 fd ff ff 8b 45 08 |.E..}.........E.| +000009d0 c6 00 00 90 c9 c3 55 89 e5 53 8b 55 08 bb 00 00 |......U..S.U....| +000009e0 00 00 eb 03 83 c3 01 89 d0 8d 50 01 0f b6 00 84 |..........P.....| +000009f0 c0 75 f1 89 d8 5b 5d c3 55 89 e5 83 ec 18 8b 45 |.u...[].U......E| +00000a00 08 89 45 f4 83 7d 0c 00 79 0f 8b 45 f4 8d 50 01 |..E..}..y..E..P.| +00000a10 89 55 f4 c6 00 2d f7 5d 0c 83 ec 08 ff 75 0c ff |.U...-.].....u..| +00000a20 75 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 |u..........E..E.| +00000a30 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 |....U..E.).....U| +00000a40 89 e5 83 ec 18 8b 4d 0c ba 67 66 66 66 89 c8 f7 |......M..gfff...| +00000a50 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 89 45 f4 |.........)....E.| +00000a60 83 7d f4 00 79 0e c7 45 f4 cc cc cc 0c c7 45 0c |.}..y..E......E.| +00000a70 08 00 00 00 83 7d f4 00 74 14 83 ec 08 ff 75 f4 |.....}..t.....u.| +00000a80 ff 75 08 e8 b7 ff ff ff 83 c4 10 89 45 08 8b 4d |.u..........E..M| +00000a90 0c ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 |..gfff..........| +00000aa0 f8 1f 29 c2 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 |..)..........)..| +00000ab0 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 89 |....H0.E..P..U..| +00000ac0 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 ec 20 c7 45 |....E...U.... .E| +00000ad0 e3 30 31 32 33 c7 45 e7 34 35 36 37 c7 45 eb 38 |.0123.E.4567.E.8| +00000ae0 39 41 42 c7 45 ef 43 44 45 46 c6 45 f3 00 c7 45 |9AB.E.CDEF.E...E| +00000af0 fc 00 00 00 00 c7 45 f8 00 00 00 00 eb 43 8b 45 |......E......C.E| +00000b00 0c 25 00 00 00 f0 89 45 f4 83 7d fc 00 75 0c 83 |.%.....E..}..u..| +00000b10 7d f4 00 75 06 83 7d f8 07 75 1e 83 45 fc 01 c1 |}..u..}..u..E...| +00000b20 6d f4 1c 8b 45 08 8d 50 01 89 55 08 8d 4d e3 8b |m...E..P..U..M..| +00000b30 55 f4 01 ca 0f b6 12 88 10 c1 65 0c 04 83 45 f8 |U.........e...E.| +00000b40 01 83 7d f8 07 7e b7 8b 45 08 c6 00 00 8b 45 fc |..}..~..E.....E.| +00000b50 c9 c3 55 89 e5 83 ec 10 c7 45 f8 00 00 00 00 8b |..U......E......| +00000b60 45 08 89 45 f4 8b 45 0c 25 00 00 00 c0 89 45 f0 |E..E..E.%.....E.| +00000b70 c1 6d f0 1e c7 45 fc 00 00 00 00 eb 47 83 7d fc |.m...E......G.}.| +00000b80 0a 74 0c 83 7d f0 00 75 06 83 7d f8 00 74 1e c7 |.t..}..u..}..t..| +00000b90 45 f8 01 00 00 00 83 65 f0 07 8b 45 f0 8d 48 30 |E......e...E..H0| +00000ba0 8b 45 f4 8d 50 01 89 55 f4 89 ca 88 10 c1 65 0c |.E..P..U......e.| +00000bb0 03 8b 45 0c 25 00 00 00 e0 89 45 f0 c1 6d f0 1d |..E.%.....E..m..| +00000bc0 83 45 fc 01 83 7d fc 0a 7e b3 8b 45 f4 c6 00 00 |.E...}..~..E....| +00000bd0 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 |.U..E.).....U...| +00000be0 ec 18 8b 45 08 89 45 f4 83 ec 08 ff 75 0c ff 75 |...E..E.....u..u| +00000bf0 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 |..........E..E..| +00000c00 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 |...U..E.).....U.| +00000c10 e5 83 ec 18 8b 45 0c ba cd cc cc cc f7 e2 89 d0 |.....E..........| +00000c20 c1 e8 03 89 45 f4 83 7d f4 00 74 15 8b 45 f4 83 |....E..}..t..E..| +00000c30 ec 08 50 ff 75 08 e8 04 fe ff ff 83 c4 10 89 45 |..P.u..........E| +00000c40 08 8b 4d 0c ba cd cc cc cc 89 c8 f7 e2 c1 ea 03 |..M.............| +00000c50 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d |.........)......| +00000c60 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 8b |H0.E..P..U......| +00000c70 45 08 c9 c3 55 89 e5 83 ec 18 83 7d 10 00 79 11 |E...U......}..y.| +00000c80 83 ec 0c ff 75 0c e8 4b fd ff ff 83 c4 10 89 45 |....u..K.......E| +00000c90 10 8b 45 14 2b 45 10 89 45 f0 83 7d f0 00 7e 1d |..E.+E..E..}..~.| +00000ca0 83 7d 18 00 75 17 83 ec 04 ff 75 1c ff 75 f0 ff |.}..u.....u..u..| +00000cb0 75 08 e8 5a 00 00 00 83 c4 10 89 45 08 c7 45 f4 |u..Z.......E..E.| +00000cc0 00 00 00 00 eb 1b 8b 55 f4 8b 45 0c 8d 0c 02 8b |.......U..E.....| +00000cd0 45 08 8d 50 01 89 55 08 0f b6 11 88 10 83 45 f4 |E..P..U.......E.| +00000ce0 01 8b 45 f4 3b 45 10 7c dd 83 7d f0 00 7e 1d 83 |..E.;E.|..}..~..| +00000cf0 7d 18 00 74 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 |}..t.....u..u..u| +00000d00 08 e8 0b 00 00 00 83 c4 10 89 45 08 8b 45 08 c9 |..........E..E..| +00000d10 c3 55 89 e5 eb 12 8b 45 08 8d 50 01 89 55 08 8b |.U.....E..P..U..| +00000d20 55 10 88 10 83 6d 0c 01 83 7d 0c 00 7f e8 8b 45 |U....m...}.....E| +00000d30 08 5d c3 00 69 64 6c 65 00 2e 00 73 68 65 6c 6c |.]..idle...shell| +00000d40 00 49 4e 49 54 3a 20 66 6f 72 6b 20 66 6f 72 20 |.INIT: fork for | +00000d50 23 25 64 20 66 61 69 6c 65 64 0a 00 49 4e 49 54 |#%d failed..INIT| +00000d60 3a 20 65 78 65 63 28 30 78 25 30 38 78 29 20 66 |: exec(0x%08x) f| +00000d70 61 69 6c 65 64 0a 00 49 6e 69 74 20 73 74 61 72 |ailed..Init star| +00000d80 74 65 64 0a 00 00 00 00 0a 0a 53 70 65 6d 20 72 |ted.......Spem r| +00000d90 65 6c 69 6e 71 75 75 6e 74 20 71 75 69 20 68 75 |elinquunt qui hu| +00000da0 63 20 69 6e 74 72 61 73 74 69 21 0a 0a 0d 00 00 |c intrasti!.....| +00000db0 49 4e 49 54 3a 20 73 74 61 72 74 69 6e 67 20 75 |INIT: starting u| +00000dc0 73 65 72 20 70 72 6f 63 65 73 73 65 73 0a 00 20 |ser processes.. | +00000dd0 21 21 21 0d 0a 0a 00 00 49 4e 49 54 3a 20 74 72 |!!!.....INIT: tr| +00000de0 61 6e 73 69 74 69 6f 6e 69 6e 67 20 74 6f 20 77 |ansitioning to w| +00000df0 61 69 74 28 29 20 6d 6f 64 65 0a 00 49 4e 49 54 |ait() mode..INIT| +00000e00 3a 20 77 61 69 74 70 69 64 28 29 20 72 65 74 75 |: waitpid() retu| +00000e10 72 6e 65 64 20 25 64 3f 3f 3f 0a 00 49 4e 49 54 |rned %d???..INIT| +00000e20 3a 20 70 69 64 20 25 64 20 65 78 69 74 28 25 64 |: pid %d exit(%d| +00000e30 29 0a 00 43 68 69 6c 64 20 25 64 20 65 78 65 63 |)..Child %d exec| +00000e40 28 29 20 23 25 75 20 66 61 69 6c 65 64 0a 00 00 |() #%u failed...| +00000e50 22 15 00 00 60 15 00 00 ac 16 00 00 ac 16 00 00 |"...`...........| +00000e60 ac 16 00 00 ac 16 00 00 ac 16 00 00 ac 16 00 00 |................| +* +00000e80 1a 16 00 00 ac 16 00 00 ac 16 00 00 ac 16 00 00 |................| +00000e90 a4 15 00 00 ac 16 00 00 5b 16 00 00 ac 16 00 00 |........[.......| +00000ea0 ac 16 00 00 d6 15 00 00 00 00 00 00 00 00 00 00 |................| +00000eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00001300 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| +00001310 03 21 00 00 2c 1a 00 00 31 1a 00 00 00 00 00 00 |.!..,...1.......| +00001320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00001330 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 |................| +00001340 00 00 00 00 01 40 00 00 33 1a 00 00 00 00 00 00 |.....@..3.......| +00001350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00001370 62 60 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |b`..............| +00001380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +000013a0 00 00 00 00 2b 00 00 00 00 00 00 00 00 00 00 00 |....+...........| +000013b0 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 |................| +000013c0 00 00 00 00 03 00 01 00 00 00 00 00 2c 1a 00 00 |............,...| +000013d0 00 00 00 00 03 00 02 00 00 00 00 00 00 20 00 00 |............. ..| +000013e0 00 00 00 00 03 00 03 00 00 00 00 00 00 30 00 00 |.............0..| +000013f0 00 00 00 00 03 00 04 00 01 00 00 00 00 00 00 00 |................| +00001400 00 00 00 00 04 00 f1 ff 08 00 00 00 00 20 00 00 |............. ..| +00001410 9c 00 00 00 01 00 03 00 39 01 00 00 9c 20 00 00 |........9.... ..| +00001420 01 00 00 00 01 00 03 00 14 00 00 00 00 10 00 00 |................| +00001430 d2 00 00 00 02 00 01 00 1c 00 00 00 00 00 00 00 |................| +00001440 00 00 00 00 04 00 f1 ff 24 00 00 00 00 00 00 00 |........$.......| +00001450 00 00 00 00 04 00 f1 ff 2d 00 00 00 00 00 00 00 |........-.......| +00001460 00 00 00 00 04 00 f1 ff 36 00 00 00 00 00 00 00 |........6.......| +00001470 00 00 00 00 04 00 f1 ff 3f 00 00 00 00 00 00 00 |........?.......| +00001480 00 00 00 00 04 00 f1 ff 49 00 00 00 00 00 00 00 |........I.......| +00001490 00 00 00 00 04 00 f1 ff 52 00 00 00 00 00 00 00 |........R.......| +000014a0 00 00 00 00 04 00 f1 ff 5b 00 00 00 00 00 00 00 |........[.......| +000014b0 00 00 00 00 04 00 f1 ff 64 00 00 00 00 00 00 00 |........d.......| +000014c0 00 00 00 00 04 00 f1 ff 6e 00 00 00 00 00 00 00 |........n.......| +000014d0 00 00 00 00 04 00 f1 ff 77 00 00 00 00 00 00 00 |........w.......| +000014e0 00 00 00 00 04 00 f1 ff 7d 00 00 00 6a 13 00 00 |........}...j...| +000014f0 21 00 00 00 12 00 01 00 86 00 00 00 db 13 00 00 |!...............| +00001500 00 00 00 00 10 00 01 00 8e 00 00 00 4f 13 00 00 |............O...| +00001510 1b 00 00 00 12 00 01 00 95 00 00 00 d4 18 00 00 |................| +00001520 32 00 00 00 12 00 01 00 9c 00 00 00 03 14 00 00 |2...............| +00001530 00 00 00 00 10 00 01 00 a3 00 00 00 33 14 00 00 |............3...| +00001540 00 00 00 00 10 00 01 00 a9 00 00 00 b8 13 00 00 |................| +00001550 1b 00 00 00 12 00 01 00 b0 00 00 00 09 1a 00 00 |................| +00001560 22 00 00 00 12 00 01 00 b4 00 00 00 8c 12 00 00 |"...............| +00001570 75 00 00 00 12 00 01 00 ba 00 00 00 59 14 00 00 |u...........Y...| +00001580 75 02 00 00 12 00 01 00 c1 00 00 00 c0 17 00 00 |u...............| +00001590 8a 00 00 00 12 00 01 00 c8 00 00 00 06 19 00 00 |................| +000015a0 66 00 00 00 12 00 01 00 8f 00 00 00 fb 13 00 00 |f...............| +000015b0 00 00 00 00 10 00 01 00 d0 00 00 00 2b 14 00 00 |............+...| +000015c0 00 00 00 00 10 00 01 00 d5 00 00 00 22 13 00 00 |............"...| +000015d0 2d 00 00 00 12 00 01 00 dd 00 00 00 eb 13 00 00 |-...............| +000015e0 00 00 00 00 10 00 01 00 e2 00 00 00 74 12 00 00 |............t...| +000015f0 18 00 00 00 12 00 01 00 e7 00 00 00 8b 13 00 00 |................| +00001600 2d 00 00 00 12 00 01 00 ef 00 00 00 49 14 00 00 |-...........I...| +00001610 00 00 00 00 10 00 01 00 f6 00 00 00 f3 13 00 00 |................| +00001620 00 00 00 00 10 00 01 00 fb 00 00 00 1b 14 00 00 |................| +00001630 00 00 00 00 10 00 01 00 03 01 00 00 37 17 00 00 |............7...| +00001640 89 00 00 00 12 00 01 00 0b 01 00 00 e3 13 00 00 |................| +00001650 00 00 00 00 10 00 01 00 10 01 00 00 d2 10 00 00 |................| +00001660 a2 01 00 00 12 00 01 00 15 01 00 00 0b 14 00 00 |................| +00001670 00 00 00 00 10 00 01 00 1d 01 00 00 6c 19 00 00 |............l...| +00001680 9d 00 00 00 12 00 01 00 24 01 00 00 23 14 00 00 |........$...#...| +00001690 00 00 00 00 10 00 01 00 2c 01 00 00 4a 18 00 00 |........,...J...| +000016a0 8a 00 00 00 12 00 01 00 33 01 00 00 01 13 00 00 |........3.......| +000016b0 21 00 00 00 12 00 01 00 3c 01 00 00 13 14 00 00 |!.......<.......| +000016c0 00 00 00 00 10 00 01 00 44 01 00 00 f0 16 00 00 |........D.......| +000016d0 47 00 00 00 12 00 01 00 5d 01 00 00 d3 13 00 00 |G.......].......| +000016e0 00 00 00 00 10 00 01 00 4b 01 00 00 ce 16 00 00 |........K.......| +000016f0 22 00 00 00 12 00 01 00 52 01 00 00 3b 14 00 00 |".......R...;...| +00001700 00 00 00 00 10 00 01 00 58 01 00 00 43 14 00 00 |........X...C...| +00001710 00 00 00 00 10 00 01 00 00 69 6e 69 74 2e 63 00 |.........init.c.| +00001720 73 70 61 77 6e 5f 74 61 62 6c 65 00 70 72 6f 63 |spawn_table.proc| +00001730 65 73 73 00 75 6c 69 62 63 2e 63 00 73 70 72 69 |ess.ulibc.c.spri| +00001740 6e 74 2e 63 00 73 74 72 6c 65 6e 2e 63 00 63 76 |nt.c.strlen.c.cv| +00001750 74 64 65 63 2e 63 00 63 76 74 64 65 63 30 2e 63 |tdec.c.cvtdec0.c| +00001760 00 63 76 74 68 65 78 2e 63 00 63 76 74 6f 63 74 |.cvthex.c.cvtoct| +00001770 2e 63 00 63 76 74 75 6e 73 2e 63 00 63 76 74 75 |.c.cvtuns.c.cvtu| +00001780 6e 73 30 2e 63 00 70 61 64 73 74 72 2e 63 00 70 |ns0.c.padstr.c.p| +00001790 61 64 2e 63 00 73 77 72 69 74 65 63 68 00 77 61 |ad.c.swritech.wa| +000017a0 69 74 70 69 64 00 63 77 72 69 74 65 00 63 76 74 |itpid.cwrite.cvt| +000017b0 75 6e 73 00 67 65 74 70 69 64 00 73 6c 65 65 70 |uns.getpid.sleep| +000017c0 00 73 77 72 69 74 65 00 70 61 64 00 73 70 61 77 |.swrite.pad.spaw| +000017d0 6e 00 73 70 72 69 6e 74 00 63 76 74 68 65 78 00 |n.sprint.cvthex.| +000017e0 63 76 74 75 6e 73 30 00 6b 69 6c 6c 00 63 77 72 |cvtuns0.kill.cwr| +000017f0 69 74 65 73 00 65 78 65 63 00 77 61 69 74 00 73 |ites.exec.wait.s| +00001800 77 72 69 74 65 73 00 5f 73 74 61 72 74 00 72 65 |writes._start.re| +00001810 61 64 00 67 65 74 70 72 69 6f 00 63 76 74 64 65 |ad.getprio.cvtde| +00001820 63 30 00 66 6f 72 6b 00 6d 61 69 6e 00 67 65 74 |c0.fork.main.get| +00001830 70 70 69 64 00 70 61 64 73 74 72 00 73 65 74 70 |ppid.padstr.setp| +00001840 72 69 6f 00 63 76 74 6f 63 74 00 63 77 72 69 74 |rio.cvtoct.cwrit| +00001850 65 63 68 00 67 65 74 74 69 6d 65 00 63 76 74 64 |ech.gettime.cvtd| +00001860 65 63 00 73 74 72 6c 65 6e 00 62 6f 67 75 73 00 |ec.strlen.bogus.| +00001870 66 61 6b 65 5f 65 78 69 74 00 00 2e 73 79 6d 74 |fake_exit...symt| +00001880 61 62 00 2e 73 74 72 74 61 62 00 2e 73 68 73 74 |ab..strtab..shst| +00001890 72 74 61 62 00 2e 74 65 78 74 00 2e 72 6f 64 61 |rtab..text..roda| +000018a0 74 61 00 2e 64 61 74 61 00 2e 62 73 73 00 00 00 |ta..data..bss...| +000018b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +000018d0 00 00 00 00 00 00 00 00 1b 00 00 00 01 00 00 00 |................| +000018e0 06 00 00 00 00 10 00 00 80 00 00 00 2b 0a 00 00 |............+...| +000018f0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| +00001900 21 00 00 00 01 00 00 00 02 00 00 00 2c 1a 00 00 |!...........,...| +00001910 ac 0a 00 00 74 01 00 00 00 00 00 00 00 00 00 00 |....t...........| +00001920 04 00 00 00 00 00 00 00 29 00 00 00 01 00 00 00 |........).......| +00001930 03 00 00 00 00 20 00 00 80 10 00 00 9d 00 00 00 |..... ..........| +00001940 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00 |........ .......| +00001950 2f 00 00 00 08 00 00 00 03 00 00 00 00 30 00 00 |/............0..| +00001960 1d 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00001970 01 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 |................| +00001980 00 00 00 00 00 00 00 00 20 11 00 00 70 03 00 00 |........ ...p...| +00001990 06 00 00 00 14 00 00 00 04 00 00 00 10 00 00 00 |................| +000019a0 09 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| +000019b0 90 14 00 00 62 01 00 00 00 00 00 00 00 00 00 00 |....b...........| +000019c0 01 00 00 00 00 00 00 00 11 00 00 00 03 00 00 00 |................| +000019d0 00 00 00 00 00 00 00 00 f2 15 00 00 34 00 00 00 |............4...| +000019e0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| + +Program #1-#19 ELF binaries: +000019f0 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +00001a00 02 00 03 00 01 00 00 00 85 12 00 00 34 00 00 00 |............4...| +00001a10 38 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |8.......4. ...(.| +00001a20 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +00001a30 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +00001a40 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +00001a50 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +00001a60 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +00001a70 e5 51 81 ec a4 00 00 00 c6 45 e7 2e e8 22 02 00 |.Q.......E..."..| +00001a80 00 89 45 f0 e8 2a 02 00 00 89 45 ec e8 2a 02 00 |..E..*....E..*..| +00001a90 00 89 45 e8 83 ec 0c ff 75 ec ff 75 e8 ff 75 f0 |..E.....u..u..u.| +00001aa0 68 68 18 00 00 8d 85 67 ff ff ff 50 e8 48 02 00 |hh.....g...P.H..| +00001ab0 00 83 c4 20 83 ec 0c 8d 85 67 ff ff ff 50 e8 ff |... .....g...P..| +00001ac0 00 00 00 83 c4 10 83 ec 0c 68 81 18 00 00 e8 ef |.........h......| +00001ad0 00 00 00 83 c4 10 83 ec 04 6a 01 8d 45 e7 50 6a |.........j..E.Pj| +00001ae0 01 e8 b5 01 00 00 83 c4 10 c7 45 f4 00 00 00 00 |..........E.....| +00001af0 eb 04 83 45 f4 01 81 7d f4 ff e0 f5 05 7e f3 83 |...E...}.....~..| +00001b00 ec 04 6a 01 8d 45 e7 50 6a 01 e8 8c 01 00 00 83 |..j..E.Pj.......| +00001b10 c4 10 eb d5 55 89 e5 83 ec 08 83 ec 08 ff 75 08 |....U.........u.| +00001b20 6a 00 e8 54 01 00 00 83 c4 10 c9 c3 55 89 e5 81 |j..T........U...| +00001b30 ec 18 01 00 00 e8 49 01 00 00 89 45 f4 83 7d f4 |......I....E..}.| +00001b40 00 74 05 8b 45 f4 eb 57 e8 56 01 00 00 89 45 f4 |.t..E..W.V....E.| +00001b50 83 ec 08 ff 75 0c ff 75 08 e8 2d 01 00 00 83 c4 |....u..u..-.....| +00001b60 10 ff 75 08 ff 75 f4 68 8f 18 00 00 8d 85 f4 fe |..u..u.h........| +00001b70 ff ff 50 e8 81 01 00 00 83 c4 10 83 ec 0c 8d 85 |..P.............| +00001b80 f4 fe ff ff 50 e8 38 00 00 00 83 c4 10 83 ec 0c |....P.8.........| +00001b90 6a ff e8 dc 00 00 00 83 c4 10 b8 00 00 00 00 c9 |j...............| +00001ba0 c3 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 |.U......E..E....| +00001bb0 6a 01 8d 45 f4 50 6a 00 e8 de 00 00 00 83 c4 10 |j..E.Pj.........| +00001bc0 c9 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 9b |..U.........u...| +00001bd0 03 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 |.......E..E....P| +00001be0 ff 75 08 6a 00 e8 b1 00 00 00 83 c4 10 c9 c3 55 |.u.j...........U| +00001bf0 89 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 00 |.........u..u.j.| +00001c00 e8 96 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 |..........U.....| +00001c10 8b 45 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a |.E..E....j..E.Pj| +00001c20 01 e8 75 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec |..u........U....| +00001c30 18 83 ec 0c ff 75 08 e8 32 03 00 00 83 c4 10 89 |.....u..2.......| +00001c40 45 f4 8b 45 f4 83 ec 04 50 ff 75 08 6a 01 e8 48 |E..E....P.u.j..H| +00001c50 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec |........U.......| +00001c60 04 ff 75 0c ff 75 08 6a 01 e8 2d 00 00 00 83 c4 |..u..u.j..-.....| +00001c70 10 c9 c3 b8 00 00 00 00 cd 80 c3 b8 01 00 00 00 |................| +00001c80 cd 80 c3 b8 02 00 00 00 cd 80 c3 b8 03 00 00 00 |................| +00001c90 cd 80 c3 b8 04 00 00 00 cd 80 c3 b8 05 00 00 00 |................| +00001ca0 cd 80 c3 b8 06 00 00 00 cd 80 c3 b8 07 00 00 00 |................| +00001cb0 cd 80 c3 b8 08 00 00 00 cd 80 c3 b8 09 00 00 00 |................| +00001cc0 cd 80 c3 b8 0a 00 00 00 cd 80 c3 b8 0b 00 00 00 |................| +00001cd0 cd 80 c3 b8 0c 00 00 00 cd 80 c3 b8 ad 0b 00 00 |................| +00001ce0 cd 80 c3 50 e8 8a ff ff ff e8 76 fd ff ff 83 ec |...P......v.....| +00001cf0 0c 50 e8 7c ff ff ff eb fe 55 89 e5 83 ec 38 8d |.P.|.....U....8.| +00001d00 45 0c 83 c0 04 89 45 f4 e9 3f 02 00 00 80 7d f3 |E.....E..?....}.| +00001d10 25 0f 85 26 02 00 00 c7 45 ec 00 00 00 00 c7 45 |%..&....E......E| +00001d20 e4 20 00 00 00 c7 45 e8 00 00 00 00 8b 45 0c 8d |. ....E......E..| +00001d30 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 2d 75 |P..U.....E..}.-u| +00001d40 16 c7 45 ec 01 00 00 00 8b 45 0c 8d 50 01 89 55 |..E......E..P..U| +00001d50 0c 0f b6 00 88 45 f3 80 7d f3 30 75 40 c7 45 e4 |.....E..}.0u@.E.| +00001d60 30 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |0....E..P..U....| +00001d70 88 45 f3 eb 28 8b 55 e8 89 d0 c1 e0 02 01 d0 01 |.E..(.U.........| +00001d80 c0 89 45 e8 0f be 45 f3 83 e8 30 01 45 e8 8b 45 |..E...E...0.E..E| +00001d90 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 |..P..U.....E..}.| +00001da0 2f 7e 06 80 7d f3 39 7e cc 0f be 45 f3 83 e8 63 |/~..}.9~...E...c| +00001db0 83 f8 15 0f 87 93 01 00 00 8b 04 85 ac 18 00 00 |................| +00001dc0 ff e0 8b 45 f4 8d 50 04 89 55 f4 8b 00 88 45 f3 |...E..P..U....E.| +00001dd0 0f b6 45 f3 88 45 d0 c6 45 d1 00 83 ec 08 ff 75 |..E..E..E......u| +00001de0 e4 ff 75 ec ff 75 e8 6a 01 8d 45 d0 50 ff 75 08 |..u..u.j..E.P.u.| +00001df0 e8 17 04 00 00 83 c4 20 89 45 08 e9 4c 01 00 00 |....... .E..L...| +00001e00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d |.E..P..U......P.| +00001e10 45 d0 50 e8 78 01 00 00 83 c4 10 89 45 e0 83 ec |E.P.x.......E...| +00001e20 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 |..u..u..u..u..E.| +00001e30 50 ff 75 08 e8 d3 03 00 00 83 c4 20 89 45 08 e9 |P.u........ .E..| +00001e40 08 01 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 89 |.....E..P..U....| +00001e50 45 dc 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a ff |E.....u..u..u.j.| +00001e60 ff 75 dc ff 75 08 e8 a1 03 00 00 83 c4 20 89 45 |.u..u........ .E| +00001e70 08 e9 d6 00 00 00 8b 45 f4 8d 50 04 89 55 f4 8b |.......E..P..U..| +00001e80 00 83 ec 08 50 8d 45 d0 50 e8 d2 01 00 00 83 c4 |....P.E.P.......| +00001e90 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 |..E.....u..u..u.| +00001ea0 ff 75 e0 8d 45 d0 50 ff 75 08 e8 5d 03 00 00 83 |.u..E.P.u..]....| +00001eb0 c4 20 89 45 08 e9 92 00 00 00 8b 45 f4 8d 50 04 |. .E.......E..P.| +00001ec0 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 18 02 |.U......P.E.P...| +00001ed0 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 |......E.....u..u| +00001ee0 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 19 |..u..u..E.P.u...| +00001ef0 03 00 00 83 c4 20 89 45 08 eb 51 8b 45 f4 8d 50 |..... .E..Q.E..P| +00001f00 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 61 |..U......P.E.P.a| +00001f10 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff |.......E.....u..| +00001f20 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 |u..u..u..E.P.u..| +00001f30 d8 02 00 00 83 c4 20 89 45 08 90 eb 0f 8b 45 08 |...... .E.....E.| +00001f40 8d 50 01 89 55 08 0f b6 55 f3 88 10 8b 45 0c 8d |.P..U...U....E..| +00001f50 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 00 0f |P..U.....E..}...| +00001f60 85 a8 fd ff ff 8b 45 08 c6 00 00 90 c9 c3 55 89 |......E.......U.| +00001f70 e5 53 8b 55 08 bb 00 00 00 00 eb 03 83 c3 01 89 |.S.U............| +00001f80 d0 8d 50 01 0f b6 00 84 c0 75 f1 89 d8 5b 5d c3 |..P......u...[].| +00001f90 55 89 e5 83 ec 18 8b 45 08 89 45 f4 83 7d 0c 00 |U......E..E..}..| +00001fa0 79 0f 8b 45 f4 8d 50 01 89 55 f4 c6 00 2d f7 5d |y..E..P..U...-.]| +00001fb0 0c 83 ec 08 ff 75 0c ff 75 f4 e8 18 00 00 00 83 |.....u..u.......| +00001fc0 c4 10 89 45 f4 8b 45 f4 c6 00 00 8b 55 f4 8b 45 |...E..E.....U..E| +00001fd0 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b 4d 0c |.).....U......M.| +00001fe0 ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 f8 |.gfff...........| +00001ff0 1f 29 c2 89 d0 89 45 f4 83 7d f4 00 79 0e c7 45 |.)....E..}..y..E| +00002000 f4 cc cc cc 0c c7 45 0c 08 00 00 00 83 7d f4 00 |......E......}..| +00002010 74 14 83 ec 08 ff 75 f4 ff 75 08 e8 b7 ff ff ff |t.....u..u......| +00002020 83 c4 10 89 45 08 8b 4d 0c ba 67 66 66 66 89 c8 |....E..M..gfff..| +00002030 f7 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 c1 e0 |..........).....| +00002040 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d 48 30 8b 45 |.....)......H0.E| +00002050 08 8d 50 01 89 55 08 89 ca 88 10 8b 45 08 c9 c3 |..P..U......E...| +00002060 55 89 e5 83 ec 20 c7 45 e3 30 31 32 33 c7 45 e7 |U.... .E.0123.E.| +00002070 34 35 36 37 c7 45 eb 38 39 41 42 c7 45 ef 43 44 |4567.E.89AB.E.CD| +00002080 45 46 c6 45 f3 00 c7 45 fc 00 00 00 00 c7 45 f8 |EF.E...E......E.| +00002090 00 00 00 00 eb 43 8b 45 0c 25 00 00 00 f0 89 45 |.....C.E.%.....E| +000020a0 f4 83 7d fc 00 75 0c 83 7d f4 00 75 06 83 7d f8 |..}..u..}..u..}.| +000020b0 07 75 1e 83 45 fc 01 c1 6d f4 1c 8b 45 08 8d 50 |.u..E...m...E..P| +000020c0 01 89 55 08 8d 4d e3 8b 55 f4 01 ca 0f b6 12 88 |..U..M..U.......| +000020d0 10 c1 65 0c 04 83 45 f8 01 83 7d f8 07 7e b7 8b |..e...E...}..~..| +000020e0 45 08 c6 00 00 8b 45 fc c9 c3 55 89 e5 83 ec 10 |E.....E...U.....| +000020f0 c7 45 f8 00 00 00 00 8b 45 08 89 45 f4 8b 45 0c |.E......E..E..E.| +00002100 25 00 00 00 c0 89 45 f0 c1 6d f0 1e c7 45 fc 00 |%.....E..m...E..| +00002110 00 00 00 eb 47 83 7d fc 0a 74 0c 83 7d f0 00 75 |....G.}..t..}..u| +00002120 06 83 7d f8 00 74 1e c7 45 f8 01 00 00 00 83 65 |..}..t..E......e| +00002130 f0 07 8b 45 f0 8d 48 30 8b 45 f4 8d 50 01 89 55 |...E..H0.E..P..U| +00002140 f4 89 ca 88 10 c1 65 0c 03 8b 45 0c 25 00 00 00 |......e...E.%...| +00002150 e0 89 45 f0 c1 6d f0 1d 83 45 fc 01 83 7d fc 0a |..E..m...E...}..| +00002160 7e b3 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 |~..E.....U..E.).| +00002170 89 d0 c9 c3 55 89 e5 83 ec 18 8b 45 08 89 45 f4 |....U......E..E.| +00002180 83 ec 08 ff 75 0c ff 75 f4 e8 18 00 00 00 83 c4 |....u..u........| +00002190 10 89 45 f4 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 |..E..E.....U..E.| +000021a0 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b 45 0c ba |).....U......E..| +000021b0 cd cc cc cc f7 e2 89 d0 c1 e8 03 89 45 f4 83 7d |............E..}| +000021c0 f4 00 74 15 8b 45 f4 83 ec 08 50 ff 75 08 e8 04 |..t..E....P.u...| +000021d0 fe ff ff 83 c4 10 89 45 08 8b 4d 0c ba cd cc cc |.......E..M.....| +000021e0 cc 89 c8 f7 e2 c1 ea 03 89 d0 c1 e0 02 01 d0 01 |................| +000021f0 c0 29 c1 89 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 |.)......H0.E..P.| +00002200 89 55 08 89 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 |.U......E...U...| +00002210 ec 18 83 7d 10 00 79 11 83 ec 0c ff 75 0c e8 4b |...}..y.....u..K| +00002220 fd ff ff 83 c4 10 89 45 10 8b 45 14 2b 45 10 89 |.......E..E.+E..| +00002230 45 f0 83 7d f0 00 7e 1d 83 7d 18 00 75 17 83 ec |E..}..~..}..u...| +00002240 04 ff 75 1c ff 75 f0 ff 75 08 e8 5a 00 00 00 83 |..u..u..u..Z....| +00002250 c4 10 89 45 08 c7 45 f4 00 00 00 00 eb 1b 8b 55 |...E..E........U| +00002260 f4 8b 45 0c 8d 0c 02 8b 45 08 8d 50 01 89 55 08 |..E.....E..P..U.| +00002270 0f b6 11 88 10 83 45 f4 01 8b 45 f4 3b 45 10 7c |......E...E.;E.|| +00002280 dd 83 7d f0 00 7e 1d 83 7d 18 00 74 17 83 ec 04 |..}..~..}..t....| +00002290 ff 75 1c ff 75 f0 ff 75 08 e8 0b 00 00 00 83 c4 |.u..u..u........| +000022a0 10 89 45 08 8b 45 08 c9 c3 55 89 e5 eb 12 8b 45 |..E..E...U.....E| +000022b0 08 8d 50 01 89 55 08 8b 55 10 88 10 83 6d 0c 01 |..P..U..U....m..| +000022c0 83 7d 0c 00 7f e8 8b 45 08 5d c3 00 49 64 6c 65 |.}.....E.]..Idle| +000022d0 20 5b 25 64 5d 2c 20 73 74 61 72 74 65 64 20 40 | [%d], started @| +000022e0 20 25 75 0a 00 49 64 6c 65 20 73 74 61 72 74 65 | %u..Idle starte| +000022f0 64 0a 00 43 68 69 6c 64 20 25 64 20 65 78 65 63 |d..Child %d exec| +00002300 28 29 20 23 25 75 20 66 61 69 6c 65 64 0a 00 00 |() #%u failed...| +00002310 5e 13 00 00 9c 13 00 00 e8 14 00 00 e8 14 00 00 |^...............| +00002320 e8 14 00 00 e8 14 00 00 e8 14 00 00 e8 14 00 00 |................| +* +00002340 56 14 00 00 e8 14 00 00 e8 14 00 00 e8 14 00 00 |V...............| +00002350 e0 13 00 00 e8 14 00 00 97 14 00 00 e8 14 00 00 |................| +00002360 e8 14 00 00 12 14 00 00 00 00 00 00 00 00 00 00 |................| +00002370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00002a70 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +00002a80 03 00 01 00 00 00 00 00 68 18 00 00 00 00 00 00 |........h.......| +00002a90 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +00002aa0 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +00002ab0 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +00002ac0 04 00 f1 ff 08 00 00 00 00 00 00 00 00 00 00 00 |................| +00002ad0 04 00 f1 ff 10 00 00 00 00 00 00 00 00 00 00 00 |................| +00002ae0 04 00 f1 ff 19 00 00 00 00 00 00 00 00 00 00 00 |................| +00002af0 04 00 f1 ff 22 00 00 00 00 00 00 00 00 00 00 00 |...."...........| +00002b00 04 00 f1 ff 2b 00 00 00 00 00 00 00 00 00 00 00 |....+...........| +00002b10 04 00 f1 ff 35 00 00 00 00 00 00 00 00 00 00 00 |....5...........| +00002b20 04 00 f1 ff 3e 00 00 00 00 00 00 00 00 00 00 00 |....>...........| +00002b30 04 00 f1 ff 47 00 00 00 00 00 00 00 00 00 00 00 |....G...........| +00002b40 04 00 f1 ff 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........| +00002b50 04 00 f1 ff 5a 00 00 00 00 00 00 00 00 00 00 00 |....Z...........| +00002b60 04 00 f1 ff 63 00 00 00 00 00 00 00 00 00 00 00 |....c...........| +00002b70 04 00 f1 ff 69 00 00 00 a6 11 00 00 21 00 00 00 |....i.......!...| +00002b80 12 00 01 00 72 00 00 00 17 12 00 00 00 00 00 00 |....r...........| +00002b90 10 00 01 00 7a 00 00 00 8b 11 00 00 1b 00 00 00 |....z...........| +00002ba0 12 00 01 00 81 00 00 00 10 17 00 00 32 00 00 00 |............2...| +00002bb0 12 00 01 00 88 00 00 00 3f 12 00 00 00 00 00 00 |........?.......| +00002bc0 10 00 01 00 8f 00 00 00 6f 12 00 00 00 00 00 00 |........o.......| +00002bd0 10 00 01 00 95 00 00 00 f4 11 00 00 1b 00 00 00 |................| +00002be0 12 00 01 00 9c 00 00 00 45 18 00 00 22 00 00 00 |........E..."...| +00002bf0 12 00 01 00 a0 00 00 00 c8 10 00 00 75 00 00 00 |............u...| +00002c00 12 00 01 00 a6 00 00 00 95 12 00 00 75 02 00 00 |............u...| +00002c10 12 00 01 00 ad 00 00 00 fc 15 00 00 8a 00 00 00 |................| +00002c20 12 00 01 00 b4 00 00 00 42 17 00 00 66 00 00 00 |........B...f...| +00002c30 12 00 01 00 7b 00 00 00 37 12 00 00 00 00 00 00 |....{...7.......| +00002c40 10 00 01 00 bc 00 00 00 67 12 00 00 00 00 00 00 |........g.......| +00002c50 10 00 01 00 c1 00 00 00 5e 11 00 00 2d 00 00 00 |........^...-...| +00002c60 12 00 01 00 c9 00 00 00 27 12 00 00 00 00 00 00 |........'.......| +00002c70 10 00 01 00 ce 00 00 00 b0 10 00 00 18 00 00 00 |................| +00002c80 12 00 01 00 d3 00 00 00 c7 11 00 00 2d 00 00 00 |............-...| +00002c90 12 00 01 00 db 00 00 00 85 12 00 00 00 00 00 00 |................| +00002ca0 10 00 01 00 e2 00 00 00 2f 12 00 00 00 00 00 00 |......../.......| +00002cb0 10 00 01 00 e7 00 00 00 57 12 00 00 00 00 00 00 |........W.......| +00002cc0 10 00 01 00 ef 00 00 00 73 15 00 00 89 00 00 00 |........s.......| +00002cd0 12 00 01 00 f7 00 00 00 1f 12 00 00 00 00 00 00 |................| +00002ce0 10 00 01 00 fc 00 00 00 00 10 00 00 b0 00 00 00 |................| +00002cf0 12 00 01 00 01 01 00 00 47 12 00 00 00 00 00 00 |........G.......| +00002d00 10 00 01 00 09 01 00 00 a8 17 00 00 9d 00 00 00 |................| +00002d10 12 00 01 00 10 01 00 00 5f 12 00 00 00 00 00 00 |........_.......| +00002d20 10 00 01 00 18 01 00 00 86 16 00 00 8a 00 00 00 |................| +00002d30 12 00 01 00 1f 01 00 00 3d 11 00 00 21 00 00 00 |........=...!...| +00002d40 12 00 01 00 28 01 00 00 4f 12 00 00 00 00 00 00 |....(...O.......| +00002d50 10 00 01 00 30 01 00 00 2c 15 00 00 47 00 00 00 |....0...,...G...| +00002d60 12 00 01 00 49 01 00 00 0f 12 00 00 00 00 00 00 |....I...........| +00002d70 10 00 01 00 37 01 00 00 0a 15 00 00 22 00 00 00 |....7......."...| +00002d80 12 00 01 00 3e 01 00 00 77 12 00 00 00 00 00 00 |....>...w.......| +00002d90 10 00 01 00 44 01 00 00 7f 12 00 00 00 00 00 00 |....D...........| +00002da0 10 00 01 00 00 69 64 6c 65 2e 63 00 75 6c 69 62 |.....idle.c.ulib| +00002db0 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 74 72 |c.c.sprint.c.str| +00002dc0 6c 65 6e 2e 63 00 63 76 74 64 65 63 2e 63 00 63 |len.c.cvtdec.c.c| +00002dd0 76 74 64 65 63 30 2e 63 00 63 76 74 68 65 78 2e |vtdec0.c.cvthex.| +00002de0 63 00 63 76 74 6f 63 74 2e 63 00 63 76 74 75 6e |c.cvtoct.c.cvtun| +00002df0 73 2e 63 00 63 76 74 75 6e 73 30 2e 63 00 70 61 |s.c.cvtuns0.c.pa| +00002e00 64 73 74 72 2e 63 00 70 61 64 2e 63 00 73 77 72 |dstr.c.pad.c.swr| +00002e10 69 74 65 63 68 00 77 61 69 74 70 69 64 00 63 77 |itech.waitpid.cw| +00002e20 72 69 74 65 00 63 76 74 75 6e 73 00 67 65 74 70 |rite.cvtuns.getp| +00002e30 69 64 00 73 6c 65 65 70 00 73 77 72 69 74 65 00 |id.sleep.swrite.| +00002e40 70 61 64 00 73 70 61 77 6e 00 73 70 72 69 6e 74 |pad.spawn.sprint| +00002e50 00 63 76 74 68 65 78 00 63 76 74 75 6e 73 30 00 |.cvthex.cvtuns0.| +00002e60 6b 69 6c 6c 00 63 77 72 69 74 65 73 00 65 78 65 |kill.cwrites.exe| +00002e70 63 00 77 61 69 74 00 73 77 72 69 74 65 73 00 5f |c.wait.swrites._| +00002e80 73 74 61 72 74 00 72 65 61 64 00 67 65 74 70 72 |start.read.getpr| +00002e90 69 6f 00 63 76 74 64 65 63 30 00 66 6f 72 6b 00 |io.cvtdec0.fork.| +00002ea0 6d 61 69 6e 00 67 65 74 70 70 69 64 00 70 61 64 |main.getppid.pad| +00002eb0 73 74 72 00 73 65 74 70 72 69 6f 00 63 76 74 6f |str.setprio.cvto| +00002ec0 63 74 00 63 77 72 69 74 65 63 68 00 67 65 74 74 |ct.cwritech.gett| +00002ed0 69 6d 65 00 63 76 74 64 65 63 00 73 74 72 6c 65 |ime.cvtdec.strle| +00002ee0 6e 00 62 6f 67 75 73 00 66 61 6b 65 5f 65 78 69 |n.bogus.fake_exi| +00002ef0 74 00 00 2e 73 79 6d 74 61 62 00 2e 73 74 72 74 |t...symtab..strt| +00002f00 61 62 00 2e 73 68 73 74 72 74 61 62 00 2e 74 65 |ab..shstrtab..te| +00002f10 78 74 00 2e 72 6f 64 61 74 61 00 2e 64 61 74 61 |xt..rodata..data| +00002f20 00 2e 62 73 73 00 00 00 00 00 00 00 00 00 00 00 |..bss...........| +00002f30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00002f50 1b 00 00 00 01 00 00 00 06 00 00 00 00 10 00 00 |................| +00002f60 74 00 00 00 67 08 00 00 00 00 00 00 00 00 00 00 |t...g...........| +00002f70 01 00 00 00 00 00 00 00 21 00 00 00 01 00 00 00 |........!.......| +00002f80 02 00 00 00 68 18 00 00 dc 08 00 00 9c 00 00 00 |....h...........| +00002f90 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................| +00002fa0 29 00 00 00 01 00 00 00 03 00 00 00 00 20 00 00 |)............ ..| +00002fb0 74 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |t...............| +00002fc0 01 00 00 00 00 00 00 00 2f 00 00 00 08 00 00 00 |......../.......| +00002fd0 03 00 00 00 00 20 00 00 74 10 00 00 00 00 00 00 |..... ..t.......| +00002fe0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| +00002ff0 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................| +00003000 74 10 00 00 40 03 00 00 06 00 00 00 11 00 00 00 |t...@...........| +00003010 04 00 00 00 10 00 00 00 09 00 00 00 03 00 00 00 |................| +00003020 00 00 00 00 00 00 00 00 b4 13 00 00 4e 01 00 00 |............N...| +00003030 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| +00003040 11 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| +00003050 02 15 00 00 34 00 00 00 00 00 00 00 00 00 00 00 |....4...........| +00003060 01 00 00 00 00 00 00 00 7f 45 4c 46 01 01 01 00 |.........ELF....| +00003070 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 |................| +00003080 87 15 00 00 34 00 00 00 f4 19 00 00 00 00 00 00 |....4...........| +00003090 34 00 20 00 02 00 28 00 08 00 07 00 01 00 00 00 |4. ...(.........| +000030a0 80 00 00 00 00 10 00 00 00 10 00 00 20 14 00 00 |............ ...| +000030b0 08 20 00 00 07 00 00 00 20 00 00 00 51 e5 74 64 |. ...... ...Q.td| +000030c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000030d0 00 00 00 00 07 00 00 00 10 00 00 00 00 00 00 00 |................| +000030e0 00 00 00 00 00 00 00 00 55 89 e5 83 ec 18 83 ec |........U.......| +000030f0 0c 68 38 1c 00 00 e8 b6 04 00 00 83 c4 10 c7 45 |.h8............E| +00003100 f4 00 20 00 00 eb 23 83 ec 0c 6a 20 e8 7f 04 00 |.. ...#...j ....| +00003110 00 83 c4 10 8b 45 f4 0f b6 40 05 0f be c0 83 ec |.....E...@......| +00003120 0c 50 e8 69 04 00 00 83 c4 10 8b 45 f4 8b 00 3d |.P.i.......E...=| +00003130 62 60 01 00 75 d1 83 ec 0c 68 70 1c 00 00 e8 6e |b`..u....hp....n| +00003140 04 00 00 83 c4 10 90 c9 c3 55 89 e5 53 81 ec a4 |.........U..S...| +00003150 00 00 00 8b 45 08 88 85 64 ff ff ff 80 bd 64 ff |....E...d.....d.| +00003160 ff ff 68 75 0a e8 7e ff ff ff e9 e0 00 00 00 80 |..hu..~.........| +00003170 bd 64 ff ff ff 78 75 0c c6 05 00 30 00 00 01 e9 |.d...xu....0....| +00003180 cb 00 00 00 80 bd 64 ff ff ff 2a 75 40 bb 00 20 |......d...*u@.. | +00003190 00 00 eb 2b 8d 53 08 8b 03 83 ec 08 52 50 e8 0f |...+.S......RP..| +000031a0 03 00 00 83 c4 10 89 45 f0 83 7d f0 00 7e 0d a1 |.......E..}..~..| +000031b0 04 30 00 00 83 c0 01 a3 04 30 00 00 83 c3 30 8b |.0.......0....0.| +000031c0 03 3d 62 60 01 00 75 cc e9 82 00 00 00 bb 00 20 |.=b`..u........ | +000031d0 00 00 eb 3c 0f b6 43 05 38 85 64 ff ff ff 75 2d |...<..C.8.d...u-| +000031e0 8d 53 08 8b 03 83 ec 08 52 50 e8 c3 02 00 00 83 |.S......RP......| +000031f0 c4 10 89 45 f4 83 7d f4 00 7e 0d a1 04 30 00 00 |...E..}..~...0..| +00003200 83 c0 01 a3 04 30 00 00 8b 45 f4 eb 47 83 c3 30 |.....0...E..G..0| +00003210 8b 03 3d 62 60 01 00 75 bb 0f be 85 64 ff ff ff |..=b`..u....d...| +00003220 83 ec 04 50 68 a1 1c 00 00 8d 85 70 ff ff ff 50 |...Ph......p...P| +00003230 e8 4a 04 00 00 83 c4 10 83 ec 0c 8d 85 70 ff ff |.J...........p..| +00003240 ff 50 e8 6a 03 00 00 83 c4 10 e8 99 fe ff ff b8 |.P.j............| +00003250 00 00 00 00 8b 5d fc c9 c3 55 89 e5 83 ec 10 8b |.....]...U......| +00003260 45 0c 8d 50 ff 8b 45 08 01 d0 89 45 fc eb 18 8b |E..P..E....E....| +00003270 45 fc 0f b6 00 3c 0a 74 0a 8b 45 fc 0f b6 00 3c |E....<.t..E....<| +00003280 0d 75 0a 83 6d 0c 01 83 7d 0c 00 7f e2 83 7d 0c |.u..m...}.....}.| +00003290 00 7e 0b 8b 55 0c 8b 45 08 01 d0 c6 00 00 8b 45 |.~..U..E.......E| +000032a0 0c c9 c3 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 e5 |....L$.....q.U..| +000032b0 51 81 ec 24 01 00 00 83 ec 0c 68 ba 1c 00 00 e8 |Q..$......h.....| +000032c0 ed 02 00 00 83 c4 10 e8 1c fe ff ff e9 90 01 00 |................| +000032d0 00 83 ec 0c 68 ca 1c 00 00 e8 d3 02 00 00 83 c4 |....h...........| +000032e0 10 83 ec 04 68 80 00 00 00 8d 85 e0 fe ff ff 50 |....h..........P| +000032f0 6a 01 e8 22 03 00 00 83 c4 10 89 45 ec 83 7d ec |j..".......E..}.| +00003300 02 0f 8e 56 01 00 00 83 ec 08 ff 75 ec 8d 85 e0 |...V.......u....| +00003310 fe ff ff 50 e8 40 ff ff ff 83 c4 10 89 45 ec 83 |...P.@.......E..| +00003320 7d ec 01 0f 8e 37 01 00 00 c7 45 f0 00 00 00 00 |}....7....E.....| +00003330 8d 85 e0 fe ff ff 89 45 f4 eb 12 8b 45 f4 0f b6 |.......E....E...| +00003340 00 3c 40 74 12 83 45 f0 01 83 45 f4 01 8b 45 f0 |.<@t..E...E...E.| +00003350 3b 45 ec 7c e6 eb 01 90 8b 45 f0 3b 45 ec 0f 8d |;E.|.....E.;E...| +00003360 fd 00 00 00 83 45 f4 01 eb 60 8b 45 f4 0f b6 00 |.....E...`.E....| +00003370 0f be c0 83 ec 0c 50 e8 cd fd ff ff 83 c4 10 89 |......P.........| +00003380 45 e8 83 7d e8 00 79 33 8b 45 f4 0f b6 00 0f be |E..}..y3.E......| +00003390 c0 ff 75 e8 50 68 d0 1c 00 00 8d 85 60 ff ff ff |..u.Ph......`...| +000033a0 50 e8 d9 02 00 00 83 c4 10 83 ec 0c 8d 85 60 ff |P.............`.| +000033b0 ff ff 50 e8 90 01 00 00 83 c4 10 0f b6 05 00 30 |..P............0| +000033c0 00 00 84 c0 75 10 83 45 f4 01 8b 45 f4 0f b6 00 |....u..E...E....| +000033d0 84 c0 75 96 eb 79 90 eb 76 83 ec 08 8d 45 e0 50 |..u..y..v....E.P| +000033e0 6a 00 e8 1a 02 00 00 83 c4 10 89 45 e4 83 7d e4 |j..........E..}.| +000033f0 fc 74 67 83 7d e4 00 7f 1c 83 ec 04 ff 75 e4 68 |.tg.}........u.h| +00003400 f4 1c 00 00 8d 85 60 ff ff ff 50 e8 6f 02 00 00 |......`...P.o...| +00003410 83 c4 10 eb 28 a1 04 30 00 00 83 e8 01 a3 04 30 |....(..0.......0| +00003420 00 00 8b 45 e0 50 ff 75 e4 68 12 1d 00 00 8d 85 |...E.P.u.h......| +00003430 60 ff ff ff 50 e8 45 02 00 00 83 c4 10 83 ec 0c |`...P.E.........| +00003440 8d 85 60 ff ff ff 50 e8 65 01 00 00 83 c4 10 a1 |..`...P.e.......| +00003450 04 30 00 00 85 c0 7f 81 eb 07 90 eb 04 90 eb 01 |.0..............| +00003460 90 0f b6 05 00 30 00 00 84 c0 0f 84 61 fe ff ff |.....0......a...| +00003470 83 ec 0c 68 30 1d 00 00 e8 cb 00 00 00 83 c4 10 |...h0...........| +00003480 83 ec 0c 6a 01 e8 6f 01 00 00 83 c4 10 b8 00 00 |...j..o.........| +00003490 00 00 8b 4d fc c9 8d 61 fc c3 55 89 e5 83 ec 08 |...M...a..U.....| +000034a0 83 ec 08 ff 75 08 6a 00 e8 54 01 00 00 83 c4 10 |....u.j..T......| +000034b0 c9 c3 55 89 e5 81 ec 18 01 00 00 e8 49 01 00 00 |..U.........I...| +000034c0 89 45 f4 83 7d f4 00 74 05 8b 45 f4 eb 57 e8 56 |.E..}..t..E..W.V| +000034d0 01 00 00 89 45 f4 83 ec 08 ff 75 0c ff 75 08 e8 |....E.....u..u..| +000034e0 2d 01 00 00 83 c4 10 ff 75 08 ff 75 f4 68 4a 1d |-.......u..u.hJ.| +000034f0 00 00 8d 85 f4 fe ff ff 50 e8 81 01 00 00 83 c4 |........P.......| +00003500 10 83 ec 0c 8d 85 f4 fe ff ff 50 e8 38 00 00 00 |..........P.8...| +00003510 83 c4 10 83 ec 0c 6a ff e8 dc 00 00 00 83 c4 10 |......j.........| +00003520 b8 00 00 00 00 c9 c3 55 89 e5 83 ec 18 8b 45 08 |.......U......E.| +00003530 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 00 e8 de |.E....j..E.Pj...| +00003540 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 ec |........U.......| +00003550 0c ff 75 08 e8 9b 03 00 00 83 c4 10 89 45 f4 8b |..u..........E..| +00003560 45 f4 83 ec 04 50 ff 75 08 6a 00 e8 b1 00 00 00 |E....P.u.j......| +00003570 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff 75 |.....U.........u| +00003580 0c ff 75 08 6a 00 e8 96 00 00 00 83 c4 10 c9 c3 |..u.j...........| +00003590 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 6a |U......E..E....j| +000035a0 01 8d 45 f4 50 6a 01 e8 75 00 00 00 83 c4 10 c9 |..E.Pj..u.......| +000035b0 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 32 03 |.U.........u..2.| +000035c0 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 ff |......E..E....P.| +000035d0 75 08 6a 01 e8 48 00 00 00 83 c4 10 c9 c3 55 89 |u.j..H........U.| +000035e0 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 01 e8 |........u..u.j..| +000035f0 2d 00 00 00 83 c4 10 c9 c3 b8 00 00 00 00 cd 80 |-...............| +00003600 c3 b8 01 00 00 00 cd 80 c3 b8 02 00 00 00 cd 80 |................| +00003610 c3 b8 03 00 00 00 cd 80 c3 b8 04 00 00 00 cd 80 |................| +00003620 c3 b8 05 00 00 00 cd 80 c3 b8 06 00 00 00 cd 80 |................| +00003630 c3 b8 07 00 00 00 cd 80 c3 b8 08 00 00 00 cd 80 |................| +00003640 c3 b8 09 00 00 00 cd 80 c3 b8 0a 00 00 00 cd 80 |................| +00003650 c3 b8 0b 00 00 00 cd 80 c3 b8 0c 00 00 00 cd 80 |................| +00003660 c3 b8 ad 0b 00 00 cd 80 c3 50 e8 8a ff ff ff e8 |.........P......| +00003670 2f fc ff ff 83 ec 0c 50 e8 7c ff ff ff eb fe 55 |/......P.|.....U| +00003680 89 e5 83 ec 38 8d 45 0c 83 c0 04 89 45 f4 e9 3f |....8.E.....E..?| +00003690 02 00 00 80 7d f3 25 0f 85 26 02 00 00 c7 45 ec |....}.%..&....E.| +000036a0 00 00 00 00 c7 45 e4 20 00 00 00 c7 45 e8 00 00 |.....E. ....E...| +000036b0 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +000036c0 f3 80 7d f3 2d 75 16 c7 45 ec 01 00 00 00 8b 45 |..}.-u..E......E| +000036d0 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 |..P..U.....E..}.| +000036e0 30 75 40 c7 45 e4 30 00 00 00 8b 45 0c 8d 50 01 |0u@.E.0....E..P.| +000036f0 89 55 0c 0f b6 00 88 45 f3 eb 28 8b 55 e8 89 d0 |.U.....E..(.U...| +00003700 c1 e0 02 01 d0 01 c0 89 45 e8 0f be 45 f3 83 e8 |........E...E...| +00003710 30 01 45 e8 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |0.E..E..P..U....| +00003720 88 45 f3 80 7d f3 2f 7e 06 80 7d f3 39 7e cc 0f |.E..}./~..}.9~..| +00003730 be 45 f3 83 e8 63 83 f8 15 0f 87 93 01 00 00 8b |.E...c..........| +00003740 04 85 68 1d 00 00 ff e0 8b 45 f4 8d 50 04 89 55 |..h......E..P..U| +00003750 f4 8b 00 88 45 f3 0f b6 45 f3 88 45 d0 c6 45 d1 |....E...E..E..E.| +00003760 00 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a 01 8d |.....u..u..u.j..| +00003770 45 d0 50 ff 75 08 e8 17 04 00 00 83 c4 20 89 45 |E.P.u........ .E| +00003780 08 e9 4c 01 00 00 8b 45 f4 8d 50 04 89 55 f4 8b |..L....E..P..U..| +00003790 00 83 ec 08 50 8d 45 d0 50 e8 78 01 00 00 83 c4 |....P.E.P.x.....| +000037a0 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 |..E.....u..u..u.| +000037b0 ff 75 e0 8d 45 d0 50 ff 75 08 e8 d3 03 00 00 83 |.u..E.P.u.......| +000037c0 c4 20 89 45 08 e9 08 01 00 00 8b 45 f4 8d 50 04 |. .E.......E..P.| +000037d0 89 55 f4 8b 00 89 45 dc 83 ec 08 ff 75 e4 ff 75 |.U....E.....u..u| +000037e0 ec ff 75 e8 6a ff ff 75 dc ff 75 08 e8 a1 03 00 |..u.j..u..u.....| +000037f0 00 83 c4 20 89 45 08 e9 d6 00 00 00 8b 45 f4 8d |... .E.......E..| +00003800 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 |P..U......P.E.P.| +00003810 d2 01 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 |........E.....u.| +00003820 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 |.u..u..u..E.P.u.| +00003830 e8 5d 03 00 00 83 c4 20 89 45 08 e9 92 00 00 00 |.]..... .E......| +00003840 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d |.E..P..U......P.| +00003850 45 d0 50 e8 18 02 00 00 83 c4 10 89 45 e0 83 ec |E.P.........E...| +00003860 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 |..u..u..u..u..E.| +00003870 50 ff 75 08 e8 19 03 00 00 83 c4 20 89 45 08 eb |P.u........ .E..| +00003880 51 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 |Q.E..P..U......P| +00003890 8d 45 d0 50 e8 61 02 00 00 83 c4 10 89 45 e0 83 |.E.P.a.......E..| +000038a0 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 |...u..u..u..u..E| +000038b0 d0 50 ff 75 08 e8 d8 02 00 00 83 c4 20 89 45 08 |.P.u........ .E.| +000038c0 90 eb 0f 8b 45 08 8d 50 01 89 55 08 0f b6 55 f3 |....E..P..U...U.| +000038d0 88 10 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +000038e0 f3 80 7d f3 00 0f 85 a8 fd ff ff 8b 45 08 c6 00 |..}.........E...| +000038f0 00 90 c9 c3 55 89 e5 53 8b 55 08 bb 00 00 00 00 |....U..S.U......| +00003900 eb 03 83 c3 01 89 d0 8d 50 01 0f b6 00 84 c0 75 |........P......u| +00003910 f1 89 d8 5b 5d c3 55 89 e5 83 ec 18 8b 45 08 89 |...[].U......E..| +00003920 45 f4 83 7d 0c 00 79 0f 8b 45 f4 8d 50 01 89 55 |E..}..y..E..P..U| +00003930 f4 c6 00 2d f7 5d 0c 83 ec 08 ff 75 0c ff 75 f4 |...-.].....u..u.| +00003940 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 00 |.........E..E...| +00003950 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 |..U..E.).....U..| +00003960 83 ec 18 8b 4d 0c ba 67 66 66 66 89 c8 f7 ea c1 |....M..gfff.....| +00003970 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 89 45 f4 83 7d |.......)....E..}| +00003980 f4 00 79 0e c7 45 f4 cc cc cc 0c c7 45 0c 08 00 |..y..E......E...| +00003990 00 00 83 7d f4 00 74 14 83 ec 08 ff 75 f4 ff 75 |...}..t.....u..u| +000039a0 08 e8 b7 ff ff ff 83 c4 10 89 45 08 8b 4d 0c ba |..........E..M..| +000039b0 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 f8 1f |gfff............| +000039c0 29 c2 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 |)..........)....| +000039d0 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 |..H0.E..P..U....| +000039e0 10 8b 45 08 c9 c3 55 89 e5 83 ec 20 c7 45 e3 30 |..E...U.... .E.0| +000039f0 31 32 33 c7 45 e7 34 35 36 37 c7 45 eb 38 39 41 |123.E.4567.E.89A| +00003a00 42 c7 45 ef 43 44 45 46 c6 45 f3 00 c7 45 fc 00 |B.E.CDEF.E...E..| +00003a10 00 00 00 c7 45 f8 00 00 00 00 eb 43 8b 45 0c 25 |....E......C.E.%| +00003a20 00 00 00 f0 89 45 f4 83 7d fc 00 75 0c 83 7d f4 |.....E..}..u..}.| +00003a30 00 75 06 83 7d f8 07 75 1e 83 45 fc 01 c1 6d f4 |.u..}..u..E...m.| +00003a40 1c 8b 45 08 8d 50 01 89 55 08 8d 4d e3 8b 55 f4 |..E..P..U..M..U.| +00003a50 01 ca 0f b6 12 88 10 c1 65 0c 04 83 45 f8 01 83 |........e...E...| +00003a60 7d f8 07 7e b7 8b 45 08 c6 00 00 8b 45 fc c9 c3 |}..~..E.....E...| +00003a70 55 89 e5 83 ec 10 c7 45 f8 00 00 00 00 8b 45 08 |U......E......E.| +00003a80 89 45 f4 8b 45 0c 25 00 00 00 c0 89 45 f0 c1 6d |.E..E.%.....E..m| +00003a90 f0 1e c7 45 fc 00 00 00 00 eb 47 83 7d fc 0a 74 |...E......G.}..t| +00003aa0 0c 83 7d f0 00 75 06 83 7d f8 00 74 1e c7 45 f8 |..}..u..}..t..E.| +00003ab0 01 00 00 00 83 65 f0 07 8b 45 f0 8d 48 30 8b 45 |.....e...E..H0.E| +00003ac0 f4 8d 50 01 89 55 f4 89 ca 88 10 c1 65 0c 03 8b |..P..U......e...| +00003ad0 45 0c 25 00 00 00 e0 89 45 f0 c1 6d f0 1d 83 45 |E.%.....E..m...E| +00003ae0 fc 01 83 7d fc 0a 7e b3 8b 45 f4 c6 00 00 8b 55 |...}..~..E.....U| +00003af0 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 |..E.).....U.....| +00003b00 8b 45 08 89 45 f4 83 ec 08 ff 75 0c ff 75 f4 e8 |.E..E.....u..u..| +00003b10 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 00 00 |........E..E....| +00003b20 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 |.U..E.).....U...| +00003b30 ec 18 8b 45 0c ba cd cc cc cc f7 e2 89 d0 c1 e8 |...E............| +00003b40 03 89 45 f4 83 7d f4 00 74 15 8b 45 f4 83 ec 08 |..E..}..t..E....| +00003b50 50 ff 75 08 e8 04 fe ff ff 83 c4 10 89 45 08 8b |P.u..........E..| +00003b60 4d 0c ba cd cc cc cc 89 c8 f7 e2 c1 ea 03 89 d0 |M...............| +00003b70 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d 48 30 |.......)......H0| +00003b80 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 8b 45 08 |.E..P..U......E.| +00003b90 c9 c3 55 89 e5 83 ec 18 83 7d 10 00 79 11 83 ec |..U......}..y...| +00003ba0 0c ff 75 0c e8 4b fd ff ff 83 c4 10 89 45 10 8b |..u..K.......E..| +00003bb0 45 14 2b 45 10 89 45 f0 83 7d f0 00 7e 1d 83 7d |E.+E..E..}..~..}| +00003bc0 18 00 75 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 08 |..u.....u..u..u.| +00003bd0 e8 5a 00 00 00 83 c4 10 89 45 08 c7 45 f4 00 00 |.Z.......E..E...| +00003be0 00 00 eb 1b 8b 55 f4 8b 45 0c 8d 0c 02 8b 45 08 |.....U..E.....E.| +00003bf0 8d 50 01 89 55 08 0f b6 11 88 10 83 45 f4 01 8b |.P..U.......E...| +00003c00 45 f4 3b 45 10 7c dd 83 7d f0 00 7e 1d 83 7d 18 |E.;E.|..}..~..}.| +00003c10 00 74 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 08 e8 |.t.....u..u..u..| +00003c20 0b 00 00 00 83 c4 10 89 45 08 8b 45 08 c9 c3 55 |........E..E...U| +00003c30 89 e5 eb 12 8b 45 08 8d 50 01 89 55 08 8b 55 10 |.....E..P..U..U.| +00003c40 88 10 83 6d 0c 01 83 7d 0c 00 7f e8 8b 45 08 5d |...m...}.....E.]| +00003c50 c3 00 00 00 75 73 65 72 41 00 41 00 33 30 00 75 |....userA.A.30.u| +00003c60 73 65 72 42 00 42 00 75 73 65 72 43 00 43 00 75 |serB.B.userC.C.u| +00003c70 73 65 72 44 00 44 00 32 30 00 75 73 65 72 45 00 |serD.D.20.userE.| +00003c80 45 00 75 73 65 72 46 00 46 00 75 73 65 72 47 00 |E.userF.F.userG.| +00003c90 47 00 31 30 00 75 73 65 72 48 00 48 00 34 00 75 |G.10.userH.H.4.u| +00003ca0 73 65 72 49 00 49 00 75 73 65 72 4a 00 4a 00 75 |serI.I.userJ.J.u| +00003cb0 73 65 72 4b 00 4b 00 38 00 75 73 65 72 4c 00 4c |serK.K.8.userL.L| +00003cc0 00 35 00 75 73 65 72 4d 00 4d 00 66 00 75 73 65 |.5.userM.M.f.use| +00003cd0 72 4e 00 4e 00 74 00 75 73 65 72 50 00 50 00 33 |rN.N.t.userP.P.3| +00003ce0 00 32 00 75 73 65 72 51 00 51 00 75 73 65 72 52 |.2.userQ.Q.userR| +00003cf0 00 52 00 31 00 75 73 65 72 53 00 53 00 31 33 00 |.R.1.userS.S.13.| +00003d00 75 73 65 72 54 00 54 00 36 00 77 00 75 73 65 72 |userT.T.6.w.user| +00003d10 55 00 55 00 57 00 75 73 65 72 56 00 56 00 6b 00 |U.U.W.userV.V.k.| +00003d20 0a 54 65 73 74 73 20 2d 20 72 75 6e 20 77 69 74 |.Tests - run wit| +00003d30 68 20 27 40 78 27 2c 20 77 68 65 72 65 20 27 78 |h '@x', where 'x| +00003d40 27 20 69 73 20 6f 6e 65 20 6f 72 20 6d 6f 72 65 |' is one or more| +00003d50 20 6f 66 3a 0a 20 00 00 0a 4f 74 68 65 72 20 63 | of:. ...Other c| +00003d60 6f 6d 6d 61 6e 64 73 3a 20 40 2a 20 28 61 6c 6c |ommands: @* (all| +00003d70 29 2c 20 40 68 20 28 68 65 6c 70 29 2c 20 40 78 |), @h (help), @x| +00003d80 20 28 65 78 69 74 29 0a 00 73 68 65 6c 6c 3a 20 | (exit)..shell: | +00003d90 75 6e 6b 6e 6f 77 6e 20 63 6d 64 20 27 25 63 27 |unknown cmd '%c'| +00003da0 0a 00 53 68 65 6c 6c 20 69 73 20 72 65 61 64 79 |..Shell is ready| +00003db0 0a 00 0a 3e 20 00 00 00 2b 2b 2b 20 53 68 65 6c |...> ...+++ Shel| +00003dc0 6c 20 73 70 61 77 6e 20 25 63 20 66 61 69 6c 65 |l spawn %c faile| +00003dd0 64 2c 20 63 6f 64 65 20 25 64 0a 00 73 68 65 6c |d, code %d..shel| +00003de0 6c 3a 20 77 61 69 74 70 69 64 28 29 20 72 65 74 |l: waitpid() ret| +00003df0 75 72 6e 65 64 20 25 64 0a 00 73 68 65 6c 6c 3a |urned %d..shell:| +00003e00 20 50 49 44 20 25 64 20 65 78 69 74 20 73 74 61 | PID %d exit sta| +00003e10 74 75 73 20 25 64 0a 00 21 21 21 20 73 68 65 6c |tus %d..!!! shel| +00003e20 6c 20 65 78 69 74 65 64 20 6c 6f 6f 70 3f 3f 3f |l exited loop???| +00003e30 0a 00 43 68 69 6c 64 20 25 64 20 65 78 65 63 28 |..Child %d exec(| +00003e40 29 20 23 25 75 20 66 61 69 6c 65 64 0a 00 00 00 |) #%u failed....| +00003e50 60 16 00 00 9e 16 00 00 ea 17 00 00 ea 17 00 00 |`...............| +00003e60 ea 17 00 00 ea 17 00 00 ea 17 00 00 ea 17 00 00 |................| +* +00003e80 58 17 00 00 ea 17 00 00 ea 17 00 00 ea 17 00 00 |X...............| +00003e90 e2 16 00 00 ea 17 00 00 99 17 00 00 ea 17 00 00 |................| +00003ea0 ea 17 00 00 14 17 00 00 00 00 00 00 00 00 00 00 |................| +00003eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +000040e0 00 00 00 00 00 00 00 00 03 00 00 00 01 41 00 00 |.............A..| +000040f0 6c 1b 00 00 72 1b 00 00 74 1b 00 00 00 00 00 00 |l...r...t.......| +00004100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004110 00 00 00 00 00 00 00 00 03 00 00 00 01 42 00 00 |.............B..| +00004120 77 1b 00 00 7d 1b 00 00 74 1b 00 00 00 00 00 00 |w...}...t.......| +00004130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004140 00 00 00 00 00 00 00 00 03 00 00 00 01 43 00 00 |.............C..| +00004150 7f 1b 00 00 85 1b 00 00 74 1b 00 00 00 00 00 00 |........t.......| +00004160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004170 00 00 00 00 00 00 00 00 04 00 00 00 01 44 00 00 |.............D..| +00004180 87 1b 00 00 8d 1b 00 00 8f 1b 00 00 00 00 00 00 |................| +00004190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000041a0 00 00 00 00 00 00 00 00 04 00 00 00 01 45 00 00 |.............E..| +000041b0 92 1b 00 00 98 1b 00 00 8f 1b 00 00 00 00 00 00 |................| +000041c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000041d0 00 00 00 00 00 00 00 00 05 00 00 00 01 46 00 00 |.............F..| +000041e0 9a 1b 00 00 a0 1b 00 00 8f 1b 00 00 00 00 00 00 |................| +000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004200 00 00 00 00 00 00 00 00 05 00 00 00 01 47 00 00 |.............G..| +00004210 a2 1b 00 00 a8 1b 00 00 aa 1b 00 00 00 00 00 00 |................| +00004220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004230 00 00 00 00 00 00 00 00 06 00 00 00 01 48 00 00 |.............H..| +00004240 ad 1b 00 00 b3 1b 00 00 b5 1b 00 00 00 00 00 00 |................| +00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004260 00 00 00 00 00 00 00 00 07 00 00 00 01 49 00 00 |.............I..| +00004270 b7 1b 00 00 bd 1b 00 00 00 00 00 00 00 00 00 00 |................| +00004280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004290 00 00 00 00 00 00 00 00 08 00 00 00 01 4a 00 00 |.............J..| +000042a0 bf 1b 00 00 c5 1b 00 00 00 00 00 00 00 00 00 00 |................| +000042b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000042c0 00 00 00 00 00 00 00 00 09 00 00 00 01 4b 00 00 |.............K..| +000042d0 c7 1b 00 00 cd 1b 00 00 cf 1b 00 00 00 00 00 00 |................| +000042e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000042f0 00 00 00 00 00 00 00 00 09 00 00 00 01 4c 00 00 |.............L..| +00004300 d1 1b 00 00 d7 1b 00 00 d9 1b 00 00 00 00 00 00 |................| +00004310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004320 00 00 00 00 00 00 00 00 0a 00 00 00 01 4d 00 00 |.............M..| +00004330 db 1b 00 00 e1 1b 00 00 d9 1b 00 00 e3 1b 00 00 |................| +00004340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004350 00 00 00 00 00 00 00 00 0a 00 00 00 01 4e 00 00 |.............N..| +00004360 e5 1b 00 00 eb 1b 00 00 d9 1b 00 00 ed 1b 00 00 |................| +00004370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004380 00 00 00 00 00 00 00 00 0b 00 00 00 01 50 00 00 |.............P..| +00004390 ef 1b 00 00 f5 1b 00 00 f7 1b 00 00 f9 1b 00 00 |................| +000043a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000043b0 00 00 00 00 00 00 00 00 0c 00 00 00 01 51 00 00 |.............Q..| +000043c0 fb 1b 00 00 01 1c 00 00 00 00 00 00 00 00 00 00 |................| +000043d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000043e0 00 00 00 00 00 00 00 00 0d 00 00 00 01 52 00 00 |.............R..| +000043f0 03 1c 00 00 09 1c 00 00 8f 1b 00 00 0b 1c 00 00 |................| +00004400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004410 00 00 00 00 00 00 00 00 0e 00 00 00 01 53 00 00 |.............S..| +00004420 0d 1c 00 00 13 1c 00 00 15 1c 00 00 00 00 00 00 |................| +00004430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004440 00 00 00 00 00 00 00 00 0f 00 00 00 01 54 00 00 |.............T..| +00004450 18 1c 00 00 1e 1c 00 00 20 1c 00 00 22 1c 00 00 |........ ..."...| +00004460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00004470 00 00 00 00 00 00 00 00 0f 00 00 00 01 55 00 00 |.............U..| +00004480 24 1c 00 00 2a 1c 00 00 20 1c 00 00 2c 1c 00 00 |$...*... ...,...| +00004490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000044a0 00 00 00 00 00 00 00 00 0f 00 00 00 01 56 00 00 |.............V..| +000044b0 2e 1c 00 00 34 1c 00 00 20 1c 00 00 36 1c 00 00 |....4... ...6...| +000044c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000044d0 00 00 00 00 00 00 00 00 62 60 01 00 00 00 00 00 |........b`......| +000044e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00004510 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 |................| +00004520 00 00 00 00 03 00 01 00 00 00 00 00 6c 1b 00 00 |............l...| +00004530 00 00 00 00 03 00 02 00 00 00 00 00 00 20 00 00 |............. ..| +00004540 00 00 00 00 03 00 03 00 00 00 00 00 00 30 00 00 |.............0..| +00004550 00 00 00 00 03 00 04 00 01 00 00 00 00 00 00 00 |................| +00004560 00 00 00 00 04 00 f1 ff 09 00 00 00 00 30 00 00 |.............0..| +00004570 01 00 00 00 01 00 04 00 16 00 00 00 04 30 00 00 |.............0..| +00004580 04 00 00 00 01 00 04 00 1f 00 00 00 00 20 00 00 |............. ..| +00004590 20 04 00 00 01 00 03 00 2b 00 00 00 00 10 00 00 | .......+.......| +000045a0 61 00 00 00 02 00 01 00 31 00 00 00 61 10 00 00 |a.......1...a...| +000045b0 10 01 00 00 02 00 01 00 35 00 00 00 71 11 00 00 |........5...q...| +000045c0 4a 00 00 00 02 00 01 00 3a 00 00 00 00 00 00 00 |J.......:.......| +000045d0 00 00 00 00 04 00 f1 ff 42 00 00 00 00 00 00 00 |........B.......| +000045e0 00 00 00 00 04 00 f1 ff 4b 00 00 00 00 00 00 00 |........K.......| +000045f0 00 00 00 00 04 00 f1 ff 54 00 00 00 00 00 00 00 |........T.......| +00004600 00 00 00 00 04 00 f1 ff 5d 00 00 00 00 00 00 00 |........].......| +00004610 00 00 00 00 04 00 f1 ff 67 00 00 00 00 00 00 00 |........g.......| +00004620 00 00 00 00 04 00 f1 ff 70 00 00 00 00 00 00 00 |........p.......| +00004630 00 00 00 00 04 00 f1 ff 79 00 00 00 00 00 00 00 |........y.......| +00004640 00 00 00 00 04 00 f1 ff 82 00 00 00 00 00 00 00 |................| +00004650 00 00 00 00 04 00 f1 ff 8c 00 00 00 00 00 00 00 |................| +00004660 00 00 00 00 04 00 f1 ff 95 00 00 00 00 00 00 00 |................| +00004670 00 00 00 00 04 00 f1 ff 9b 00 00 00 a8 14 00 00 |................| +00004680 21 00 00 00 12 00 01 00 a4 00 00 00 19 15 00 00 |!...............| +00004690 00 00 00 00 10 00 01 00 ac 00 00 00 8d 14 00 00 |................| +000046a0 1b 00 00 00 12 00 01 00 b3 00 00 00 12 1a 00 00 |................| +000046b0 32 00 00 00 12 00 01 00 ba 00 00 00 41 15 00 00 |2...........A...| +000046c0 00 00 00 00 10 00 01 00 c1 00 00 00 71 15 00 00 |............q...| +000046d0 00 00 00 00 10 00 01 00 c7 00 00 00 f6 14 00 00 |................| +000046e0 1b 00 00 00 12 00 01 00 ce 00 00 00 47 1b 00 00 |............G...| +000046f0 22 00 00 00 12 00 01 00 d2 00 00 00 ca 13 00 00 |"...............| +00004700 75 00 00 00 12 00 01 00 d8 00 00 00 97 15 00 00 |u...............| +00004710 75 02 00 00 12 00 01 00 df 00 00 00 fe 18 00 00 |u...............| +00004720 8a 00 00 00 12 00 01 00 e6 00 00 00 44 1a 00 00 |............D...| +00004730 66 00 00 00 12 00 01 00 ad 00 00 00 39 15 00 00 |f...........9...| +00004740 00 00 00 00 10 00 01 00 ee 00 00 00 69 15 00 00 |............i...| +00004750 00 00 00 00 10 00 01 00 f3 00 00 00 60 14 00 00 |............`...| +00004760 2d 00 00 00 12 00 01 00 fb 00 00 00 29 15 00 00 |-...........)...| +00004770 00 00 00 00 10 00 01 00 00 01 00 00 b2 13 00 00 |................| +00004780 18 00 00 00 12 00 01 00 05 01 00 00 c9 14 00 00 |................| +00004790 2d 00 00 00 12 00 01 00 0d 01 00 00 87 15 00 00 |-...............| +000047a0 00 00 00 00 10 00 01 00 14 01 00 00 31 15 00 00 |............1...| +000047b0 00 00 00 00 10 00 01 00 19 01 00 00 59 15 00 00 |............Y...| +000047c0 00 00 00 00 10 00 01 00 21 01 00 00 75 18 00 00 |........!...u...| +000047d0 89 00 00 00 12 00 01 00 29 01 00 00 21 15 00 00 |........)...!...| +000047e0 00 00 00 00 10 00 01 00 2e 01 00 00 bb 11 00 00 |................| +000047f0 f7 01 00 00 12 00 01 00 33 01 00 00 49 15 00 00 |........3...I...| +00004800 00 00 00 00 10 00 01 00 3b 01 00 00 aa 1a 00 00 |........;.......| +00004810 9d 00 00 00 12 00 01 00 42 01 00 00 61 15 00 00 |........B...a...| +00004820 00 00 00 00 10 00 01 00 4a 01 00 00 88 19 00 00 |........J.......| +00004830 8a 00 00 00 12 00 01 00 51 01 00 00 3f 14 00 00 |........Q...?...| +00004840 21 00 00 00 12 00 01 00 5a 01 00 00 51 15 00 00 |!.......Z...Q...| +00004850 00 00 00 00 10 00 01 00 62 01 00 00 2e 18 00 00 |........b.......| +00004860 47 00 00 00 12 00 01 00 7b 01 00 00 11 15 00 00 |G.......{.......| +00004870 00 00 00 00 10 00 01 00 69 01 00 00 0c 18 00 00 |........i.......| +00004880 22 00 00 00 12 00 01 00 70 01 00 00 79 15 00 00 |".......p...y...| +00004890 00 00 00 00 10 00 01 00 76 01 00 00 81 15 00 00 |........v.......| +000048a0 00 00 00 00 10 00 01 00 00 73 68 65 6c 6c 2e 63 |.........shell.c| +000048b0 00 74 69 6d 65 5f 74 6f 5f 73 74 6f 70 00 63 68 |.time_to_stop.ch| +000048c0 69 6c 64 72 65 6e 00 73 70 61 77 6e 5f 74 61 62 |ildren.spawn_tab| +000048d0 6c 65 00 75 73 61 67 65 00 72 75 6e 00 65 64 69 |le.usage.run.edi| +000048e0 74 00 75 6c 69 62 63 2e 63 00 73 70 72 69 6e 74 |t.ulibc.c.sprint| +000048f0 2e 63 00 73 74 72 6c 65 6e 2e 63 00 63 76 74 64 |.c.strlen.c.cvtd| +00004900 65 63 2e 63 00 63 76 74 64 65 63 30 2e 63 00 63 |ec.c.cvtdec0.c.c| +00004910 76 74 68 65 78 2e 63 00 63 76 74 6f 63 74 2e 63 |vthex.c.cvtoct.c| +00004920 00 63 76 74 75 6e 73 2e 63 00 63 76 74 75 6e 73 |.cvtuns.c.cvtuns| +00004930 30 2e 63 00 70 61 64 73 74 72 2e 63 00 70 61 64 |0.c.padstr.c.pad| +00004940 2e 63 00 73 77 72 69 74 65 63 68 00 77 61 69 74 |.c.swritech.wait| +00004950 70 69 64 00 63 77 72 69 74 65 00 63 76 74 75 6e |pid.cwrite.cvtun| +00004960 73 00 67 65 74 70 69 64 00 73 6c 65 65 70 00 73 |s.getpid.sleep.s| +00004970 77 72 69 74 65 00 70 61 64 00 73 70 61 77 6e 00 |write.pad.spawn.| +00004980 73 70 72 69 6e 74 00 63 76 74 68 65 78 00 63 76 |sprint.cvthex.cv| +00004990 74 75 6e 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 |tuns0.kill.cwrit| +000049a0 65 73 00 65 78 65 63 00 77 61 69 74 00 73 77 72 |es.exec.wait.swr| +000049b0 69 74 65 73 00 5f 73 74 61 72 74 00 72 65 61 64 |ites._start.read| +000049c0 00 67 65 74 70 72 69 6f 00 63 76 74 64 65 63 30 |.getprio.cvtdec0| +000049d0 00 66 6f 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 |.fork.main.getpp| +000049e0 69 64 00 70 61 64 73 74 72 00 73 65 74 70 72 69 |id.padstr.setpri| +000049f0 6f 00 63 76 74 6f 63 74 00 63 77 72 69 74 65 63 |o.cvtoct.cwritec| +00004a00 68 00 67 65 74 74 69 6d 65 00 63 76 74 64 65 63 |h.gettime.cvtdec| +00004a10 00 73 74 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 |.strlen.bogus.fa| +00004a20 6b 65 5f 65 78 69 74 00 00 2e 73 79 6d 74 61 62 |ke_exit...symtab| +00004a30 00 2e 73 74 72 74 61 62 00 2e 73 68 73 74 72 74 |..strtab..shstrt| +00004a40 61 62 00 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 |ab..text..rodata| +00004a50 00 2e 64 61 74 61 00 2e 62 73 73 00 00 00 00 00 |..data..bss.....| +00004a60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00004a80 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +00004a90 00 10 00 00 80 00 00 00 69 0b 00 00 00 00 00 00 |........i.......| +00004aa0 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +00004ab0 01 00 00 00 02 00 00 00 6c 1b 00 00 ec 0b 00 00 |........l.......| +00004ac0 54 02 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |T...............| +00004ad0 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +00004ae0 00 20 00 00 80 10 00 00 20 04 00 00 00 00 00 00 |. ...... .......| +00004af0 00 00 00 00 20 00 00 00 00 00 00 00 2f 00 00 00 |.... ......./...| +00004b00 08 00 00 00 03 00 00 00 00 30 00 00 a0 14 00 00 |.........0......| +00004b10 08 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +00004b20 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +00004b30 00 00 00 00 a0 14 00 00 a0 03 00 00 06 00 00 00 |................| +00004b40 17 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +00004b50 03 00 00 00 00 00 00 00 00 00 00 00 40 18 00 00 |............@...| +00004b60 80 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +00004b70 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +00004b80 00 00 00 00 c0 19 00 00 34 00 00 00 00 00 00 00 |........4.......| +00004b90 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +00004ba0 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +00004bb0 02 00 03 00 01 00 00 00 0c 14 00 00 34 00 00 00 |............4...| +00004bc0 6c 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |l.......4. ...(.| +00004bd0 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +00004be0 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +00004bf0 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +00004c00 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +00004c10 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +00004c20 e5 53 51 81 ec a0 00 00 00 89 cb c7 45 f4 1e 00 |.SQ.........E...| +00004c30 00 00 c6 45 f3 31 8b 03 83 f8 02 74 1e 83 f8 03 |...E.1.....t....| +00004c40 75 2c 8b 43 04 83 c0 08 8b 00 83 ec 08 6a 0a 50 |u,.C.........j.P| +00004c50 e8 50 06 00 00 83 c4 10 89 45 f4 8b 43 04 83 c0 |.P.......E..C...| +00004c60 04 8b 00 0f b6 00 88 45 f3 e9 a7 00 00 00 8b 43 |.......E.......C| +00004c70 04 8b 00 ff 33 50 68 60 1a 00 00 8d 85 60 ff ff |....3Ph`.....`..| +00004c80 ff 50 e8 a9 03 00 00 83 c4 10 83 ec 0c 8d 85 60 |.P.............`| +00004c90 ff ff ff 50 e8 60 02 00 00 83 c4 10 c7 45 ec 00 |...P.`.......E..| +00004ca0 00 00 00 eb 59 8b 03 8d 14 85 00 00 00 00 8b 43 |....Y..........C| +00004cb0 04 01 d0 8b 00 85 c0 74 12 8b 03 8d 14 85 00 00 |.......t........| +00004cc0 00 00 8b 43 04 01 d0 8b 00 eb 05 b8 74 1a 00 00 |...C........t...| +00004cd0 83 ec 04 50 68 7b 1a 00 00 8d 85 60 ff ff ff 50 |...Ph{.....`...P| +00004ce0 e8 4b 03 00 00 83 c4 10 83 ec 0c 8d 85 60 ff ff |.K...........`..| +00004cf0 ff 50 e8 02 02 00 00 83 c4 10 83 45 ec 01 8b 45 |.P.........E...E| +00004d00 ec 3b 03 7e a0 83 ec 0c 68 7f 1a 00 00 e8 e7 01 |.;.~....h.......| +00004d10 00 00 83 c4 10 0f be 45 f3 83 ec 0c 50 e8 1f 02 |.......E....P...| +00004d20 00 00 83 c4 10 89 45 e0 83 7d e0 01 74 2e 0f be |......E..}..t...| +00004d30 45 f3 ff 75 e0 50 68 81 1a 00 00 8d 85 60 ff ff |E..u.Ph......`..| +00004d40 ff 50 e8 e9 02 00 00 83 c4 10 83 ec 0c 8d 85 60 |.P.............`| +00004d50 ff ff ff 50 e8 a0 01 00 00 83 c4 10 c7 45 e8 00 |...P.........E..| +00004d60 00 00 00 eb 61 c7 45 e4 00 00 00 00 eb 04 83 45 |....a.E........E| +00004d70 e4 01 81 7d e4 9f 25 26 00 7e f3 0f be 45 f3 83 |...}..%&.~...E..| +00004d80 ec 0c 50 e8 b9 01 00 00 83 c4 10 89 45 e0 83 7d |..P.........E..}| +00004d90 e0 01 74 2e 0f be 45 f3 ff 75 e0 50 68 9e 1a 00 |..t...E..u.Ph...| +00004da0 00 8d 85 60 ff ff ff 50 e8 83 02 00 00 83 c4 10 |...`...P........| +00004db0 83 ec 0c 8d 85 60 ff ff ff 50 e8 3a 01 00 00 83 |.....`...P.:....| +00004dc0 c4 10 83 45 e8 01 8b 45 e8 3b 45 f4 7c 97 83 ec |...E...E.;E.|...| +00004dd0 0c 6a 00 e8 d2 01 00 00 83 c4 10 c7 85 5c ff ff |.j...........\..| +00004de0 ff 2a 31 2a 00 0f b6 45 f3 88 85 5d ff ff ff 83 |.*1*...E...]....| +00004df0 ec 04 6a 03 8d 85 5c ff ff ff 50 6a 01 e8 d0 01 |..j...\...Pj....| +00004e00 00 00 83 c4 10 89 45 e0 83 7d e0 03 74 2e 0f be |......E..}..t...| +00004e10 45 f3 ff 75 e0 50 68 bc 1a 00 00 8d 85 60 ff ff |E..u.Ph......`..| +00004e20 ff 50 e8 09 02 00 00 83 c4 10 83 ec 0c 8d 85 60 |.P.............`| +00004e30 ff ff ff 50 e8 c0 00 00 00 83 c4 10 b8 2a 00 00 |...P.........*..| +00004e40 00 8d 65 f8 59 5b 5d 8d 61 fc c3 55 89 e5 83 ec |..e.Y[].a..U....| +00004e50 08 83 ec 08 ff 75 08 6a 00 e8 54 01 00 00 83 c4 |.....u.j..T.....| +00004e60 10 c9 c3 55 89 e5 81 ec 18 01 00 00 e8 49 01 00 |...U.........I..| +00004e70 00 89 45 f4 83 7d f4 00 74 05 8b 45 f4 eb 57 e8 |..E..}..t..E..W.| +00004e80 56 01 00 00 89 45 f4 83 ec 08 ff 75 0c ff 75 08 |V....E.....u..u.| +00004e90 e8 2d 01 00 00 83 c4 10 ff 75 08 ff 75 f4 68 db |.-.......u..u.h.| +00004ea0 1a 00 00 8d 85 f4 fe ff ff 50 e8 81 01 00 00 83 |.........P......| +00004eb0 c4 10 83 ec 0c 8d 85 f4 fe ff ff 50 e8 38 00 00 |...........P.8..| +00004ec0 00 83 c4 10 83 ec 0c 6a ff e8 dc 00 00 00 83 c4 |.......j........| +00004ed0 10 b8 00 00 00 00 c9 c3 55 89 e5 83 ec 18 8b 45 |........U......E| +00004ee0 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 00 e8 |..E....j..E.Pj..| +00004ef0 de 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 |.........U......| +00004f00 ec 0c ff 75 08 e8 0d 04 00 00 83 c4 10 89 45 f4 |...u..........E.| +00004f10 8b 45 f4 83 ec 04 50 ff 75 08 6a 00 e8 b1 00 00 |.E....P.u.j.....| +00004f20 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff |......U.........| +00004f30 75 0c ff 75 08 6a 00 e8 96 00 00 00 83 c4 10 c9 |u..u.j..........| +00004f40 c3 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 |.U......E..E....| +00004f50 6a 01 8d 45 f4 50 6a 01 e8 75 00 00 00 83 c4 10 |j..E.Pj..u......| +00004f60 c9 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 a4 |..U.........u...| +00004f70 03 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 |.......E..E....P| +00004f80 ff 75 08 6a 01 e8 48 00 00 00 83 c4 10 c9 c3 55 |.u.j..H........U| +00004f90 89 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 01 |.........u..u.j.| +00004fa0 e8 2d 00 00 00 83 c4 10 c9 c3 b8 00 00 00 00 cd |.-..............| +00004fb0 80 c3 b8 01 00 00 00 cd 80 c3 b8 02 00 00 00 cd |................| +00004fc0 80 c3 b8 03 00 00 00 cd 80 c3 b8 04 00 00 00 cd |................| +00004fd0 80 c3 b8 05 00 00 00 cd 80 c3 b8 06 00 00 00 cd |................| +00004fe0 80 c3 b8 07 00 00 00 cd 80 c3 b8 08 00 00 00 cd |................| +00004ff0 80 c3 b8 09 00 00 00 cd 80 c3 b8 0a 00 00 00 cd |................| +00005000 80 c3 b8 0b 00 00 00 cd 80 c3 b8 0c 00 00 00 cd |................| +00005010 80 c3 b8 ad 0b 00 00 cd 80 c3 50 e8 8a ff ff ff |..........P.....| +00005020 e8 ef fb ff ff 83 ec 0c 50 e8 7c ff ff ff eb fe |........P.|.....| +00005030 55 89 e5 83 ec 38 8d 45 0c 83 c0 04 89 45 f4 e9 |U....8.E.....E..| +00005040 3f 02 00 00 80 7d f3 25 0f 85 26 02 00 00 c7 45 |?....}.%..&....E| +00005050 ec 00 00 00 00 c7 45 e4 20 00 00 00 c7 45 e8 00 |......E. ....E..| +00005060 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 |....E..P..U.....| +00005070 45 f3 80 7d f3 2d 75 16 c7 45 ec 01 00 00 00 8b |E..}.-u..E......| +00005080 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d |E..P..U.....E..}| +00005090 f3 30 75 40 c7 45 e4 30 00 00 00 8b 45 0c 8d 50 |.0u@.E.0....E..P| +000050a0 01 89 55 0c 0f b6 00 88 45 f3 eb 28 8b 55 e8 89 |..U.....E..(.U..| +000050b0 d0 c1 e0 02 01 d0 01 c0 89 45 e8 0f be 45 f3 83 |.........E...E..| +000050c0 e8 30 01 45 e8 8b 45 0c 8d 50 01 89 55 0c 0f b6 |.0.E..E..P..U...| +000050d0 00 88 45 f3 80 7d f3 2f 7e 06 80 7d f3 39 7e cc |..E..}./~..}.9~.| +000050e0 0f be 45 f3 83 e8 63 83 f8 15 0f 87 93 01 00 00 |..E...c.........| +000050f0 8b 04 85 f8 1a 00 00 ff e0 8b 45 f4 8d 50 04 89 |..........E..P..| +00005100 55 f4 8b 00 88 45 f3 0f b6 45 f3 88 45 d0 c6 45 |U....E...E..E..E| +00005110 d1 00 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a 01 |......u..u..u.j.| +00005120 8d 45 d0 50 ff 75 08 e8 89 04 00 00 83 c4 20 89 |.E.P.u........ .| +00005130 45 08 e9 4c 01 00 00 8b 45 f4 8d 50 04 89 55 f4 |E..L....E..P..U.| +00005140 8b 00 83 ec 08 50 8d 45 d0 50 e8 ea 01 00 00 83 |.....P.E.P......| +00005150 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 |...E.....u..u..u| +00005160 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 45 04 00 00 |..u..E.P.u..E...| +00005170 83 c4 20 89 45 08 e9 08 01 00 00 8b 45 f4 8d 50 |.. .E.......E..P| +00005180 04 89 55 f4 8b 00 89 45 dc 83 ec 08 ff 75 e4 ff |..U....E.....u..| +00005190 75 ec ff 75 e8 6a ff ff 75 dc ff 75 08 e8 13 04 |u..u.j..u..u....| +000051a0 00 00 83 c4 20 89 45 08 e9 d6 00 00 00 8b 45 f4 |.... .E.......E.| +000051b0 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 |.P..U......P.E.P| +000051c0 e8 44 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 |.D.......E.....u| +000051d0 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 |..u..u..u..E.P.u| +000051e0 08 e8 cf 03 00 00 83 c4 20 89 45 08 e9 92 00 00 |........ .E.....| +000051f0 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 |..E..P..U......P| +00005200 8d 45 d0 50 e8 8a 02 00 00 83 c4 10 89 45 e0 83 |.E.P.........E..| +00005210 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 |...u..u..u..u..E| +00005220 d0 50 ff 75 08 e8 8b 03 00 00 83 c4 20 89 45 08 |.P.u........ .E.| +00005230 eb 51 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 |.Q.E..P..U......| +00005240 50 8d 45 d0 50 e8 d3 02 00 00 83 c4 10 89 45 e0 |P.E.P.........E.| +00005250 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d |....u..u..u..u..| +00005260 45 d0 50 ff 75 08 e8 4a 03 00 00 83 c4 20 89 45 |E.P.u..J..... .E| +00005270 08 90 eb 0f 8b 45 08 8d 50 01 89 55 08 0f b6 55 |.....E..P..U...U| +00005280 f3 88 10 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 |....E..P..U.....| +00005290 45 f3 80 7d f3 00 0f 85 a8 fd ff ff 8b 45 08 c6 |E..}.........E..| +000052a0 00 00 90 c9 c3 55 89 e5 53 83 ec 14 8b 45 08 8b |.....U..S....E..| +000052b0 4d 0c bb 00 00 00 00 c6 45 eb 39 c7 45 f8 01 00 |M.......E.9.E...| +000052c0 00 00 0f b6 10 80 fa 2d 75 0a c7 45 f8 ff ff ff |.......-u..E....| +000052d0 ff 83 c0 01 83 f9 0a 74 2b 89 ca 83 c2 2f 88 55 |.......t+..../.U| +000052e0 eb eb 21 0f b6 10 80 fa 2f 7e 20 0f b6 10 38 55 |..!...../~ ...8U| +000052f0 eb 7c 18 0f af d9 0f b6 10 0f be d2 01 da 8d 5a |.|.............Z| +00005300 d0 83 c0 01 0f b6 10 84 d2 75 d8 89 d8 0f af 45 |.........u.....E| +00005310 f8 83 c4 14 5b 5d c3 55 89 e5 53 8b 55 08 bb 00 |....[].U..S.U...| +00005320 00 00 00 eb 03 83 c3 01 89 d0 8d 50 01 0f b6 00 |...........P....| +00005330 84 c0 75 f1 89 d8 5b 5d c3 55 89 e5 83 ec 18 8b |..u...[].U......| +00005340 45 08 89 45 f4 83 7d 0c 00 79 0f 8b 45 f4 8d 50 |E..E..}..y..E..P| +00005350 01 89 55 f4 c6 00 2d f7 5d 0c 83 ec 08 ff 75 0c |..U...-.].....u.| +00005360 ff 75 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 |.u..........E..E| +00005370 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 |.....U..E.).....| +00005380 55 89 e5 83 ec 18 8b 4d 0c ba 67 66 66 66 89 c8 |U......M..gfff..| +00005390 f7 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 89 45 |..........)....E| +000053a0 f4 83 7d f4 00 79 0e c7 45 f4 cc cc cc 0c c7 45 |..}..y..E......E| +000053b0 0c 08 00 00 00 83 7d f4 00 74 14 83 ec 08 ff 75 |......}..t.....u| +000053c0 f4 ff 75 08 e8 b7 ff ff ff 83 c4 10 89 45 08 8b |..u..........E..| +000053d0 4d 0c ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 |M..gfff.........| +000053e0 c1 f8 1f 29 c2 89 d0 c1 e0 02 01 d0 01 c0 29 c1 |...)..........).| +000053f0 89 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 |.....H0.E..P..U.| +00005400 89 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 ec 20 c7 |.....E...U.... .| +00005410 45 e3 30 31 32 33 c7 45 e7 34 35 36 37 c7 45 eb |E.0123.E.4567.E.| +00005420 38 39 41 42 c7 45 ef 43 44 45 46 c6 45 f3 00 c7 |89AB.E.CDEF.E...| +00005430 45 fc 00 00 00 00 c7 45 f8 00 00 00 00 eb 43 8b |E......E......C.| +00005440 45 0c 25 00 00 00 f0 89 45 f4 83 7d fc 00 75 0c |E.%.....E..}..u.| +00005450 83 7d f4 00 75 06 83 7d f8 07 75 1e 83 45 fc 01 |.}..u..}..u..E..| +00005460 c1 6d f4 1c 8b 45 08 8d 50 01 89 55 08 8d 4d e3 |.m...E..P..U..M.| +00005470 8b 55 f4 01 ca 0f b6 12 88 10 c1 65 0c 04 83 45 |.U.........e...E| +00005480 f8 01 83 7d f8 07 7e b7 8b 45 08 c6 00 00 8b 45 |...}..~..E.....E| +00005490 fc c9 c3 55 89 e5 83 ec 10 c7 45 f8 00 00 00 00 |...U......E.....| +000054a0 8b 45 08 89 45 f4 8b 45 0c 25 00 00 00 c0 89 45 |.E..E..E.%.....E| +000054b0 f0 c1 6d f0 1e c7 45 fc 00 00 00 00 eb 47 83 7d |..m...E......G.}| +000054c0 fc 0a 74 0c 83 7d f0 00 75 06 83 7d f8 00 74 1e |..t..}..u..}..t.| +000054d0 c7 45 f8 01 00 00 00 83 65 f0 07 8b 45 f0 8d 48 |.E......e...E..H| +000054e0 30 8b 45 f4 8d 50 01 89 55 f4 89 ca 88 10 c1 65 |0.E..P..U......e| +000054f0 0c 03 8b 45 0c 25 00 00 00 e0 89 45 f0 c1 6d f0 |...E.%.....E..m.| +00005500 1d 83 45 fc 01 83 7d fc 0a 7e b3 8b 45 f4 c6 00 |..E...}..~..E...| +00005510 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 |..U..E.).....U..| +00005520 83 ec 18 8b 45 08 89 45 f4 83 ec 08 ff 75 0c ff |....E..E.....u..| +00005530 75 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 |u..........E..E.| +00005540 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 |....U..E.).....U| +00005550 89 e5 83 ec 18 8b 45 0c ba cd cc cc cc f7 e2 89 |......E.........| +00005560 d0 c1 e8 03 89 45 f4 83 7d f4 00 74 15 8b 45 f4 |.....E..}..t..E.| +00005570 83 ec 08 50 ff 75 08 e8 04 fe ff ff 83 c4 10 89 |...P.u..........| +00005580 45 08 8b 4d 0c ba cd cc cc cc 89 c8 f7 e2 c1 ea |E..M............| +00005590 03 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 |..........).....| +000055a0 8d 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 |.H0.E..P..U.....| +000055b0 8b 45 08 c9 c3 55 89 e5 83 ec 18 83 7d 10 00 79 |.E...U......}..y| +000055c0 11 83 ec 0c ff 75 0c e8 4b fd ff ff 83 c4 10 89 |.....u..K.......| +000055d0 45 10 8b 45 14 2b 45 10 89 45 f0 83 7d f0 00 7e |E..E.+E..E..}..~| +000055e0 1d 83 7d 18 00 75 17 83 ec 04 ff 75 1c ff 75 f0 |..}..u.....u..u.| +000055f0 ff 75 08 e8 5a 00 00 00 83 c4 10 89 45 08 c7 45 |.u..Z.......E..E| +00005600 f4 00 00 00 00 eb 1b 8b 55 f4 8b 45 0c 8d 0c 02 |........U..E....| +00005610 8b 45 08 8d 50 01 89 55 08 0f b6 11 88 10 83 45 |.E..P..U.......E| +00005620 f4 01 8b 45 f4 3b 45 10 7c dd 83 7d f0 00 7e 1d |...E.;E.|..}..~.| +00005630 83 7d 18 00 74 17 83 ec 04 ff 75 1c ff 75 f0 ff |.}..t.....u..u..| +00005640 75 08 e8 0b 00 00 00 83 c4 10 89 45 08 8b 45 08 |u..........E..E.| +00005650 c9 c3 55 89 e5 eb 12 8b 45 08 8d 50 01 89 55 08 |..U.....E..P..U.| +00005660 8b 55 10 88 10 83 6d 0c 01 83 7d 0c 00 7f e8 8b |.U....m...}.....| +00005670 45 08 5d c3 25 73 3a 20 61 72 67 63 20 25 64 2c |E.].%s: argc %d,| +00005680 20 61 72 67 73 3a 20 00 28 6e 75 6c 6c 29 00 20 | args: .(null). | +00005690 25 73 00 0a 00 3d 3d 20 25 63 2c 20 77 72 69 74 |%s...== %c, writ| +000056a0 65 20 23 31 20 72 65 74 75 72 6e 65 64 20 25 64 |e #1 returned %d| +000056b0 0a 00 3d 3d 20 25 63 2c 20 77 72 69 74 65 20 23 |..== %c, write #| +000056c0 32 20 72 65 74 75 72 6e 65 64 20 25 64 0a 00 00 |2 returned %d...| +000056d0 55 73 65 72 20 25 63 2c 20 77 72 69 74 65 20 23 |User %c, write #| +000056e0 33 20 72 65 74 75 72 6e 65 64 20 25 64 0a 00 43 |3 returned %d..C| +000056f0 68 69 6c 64 20 25 64 20 65 78 65 63 28 29 20 23 |hild %d exec() #| +00005700 25 75 20 66 61 69 6c 65 64 0a 00 00 e5 14 00 00 |%u failed.......| +00005710 23 15 00 00 6f 16 00 00 6f 16 00 00 6f 16 00 00 |#...o...o...o...| +00005720 6f 16 00 00 6f 16 00 00 6f 16 00 00 6f 16 00 00 |o...o...o...o...| +00005730 6f 16 00 00 6f 16 00 00 6f 16 00 00 dd 15 00 00 |o...o...o.......| +00005740 6f 16 00 00 6f 16 00 00 6f 16 00 00 67 15 00 00 |o...o...o...g...| +00005750 6f 16 00 00 1e 16 00 00 6f 16 00 00 6f 16 00 00 |o.......o...o...| +00005760 99 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00005770 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00005c20 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +00005c30 03 00 01 00 00 00 00 00 60 1a 00 00 00 00 00 00 |........`.......| +00005c40 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +00005c50 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +00005c60 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +00005c70 04 00 f1 ff 0b 00 00 00 00 00 00 00 00 00 00 00 |................| +00005c80 04 00 f1 ff 13 00 00 00 00 00 00 00 00 00 00 00 |................| +00005c90 04 00 f1 ff 1c 00 00 00 00 00 00 00 00 00 00 00 |................| +00005ca0 04 00 f1 ff 26 00 00 00 00 00 00 00 00 00 00 00 |....&...........| +00005cb0 04 00 f1 ff 2f 00 00 00 00 00 00 00 00 00 00 00 |..../...........| +00005cc0 04 00 f1 ff 38 00 00 00 00 00 00 00 00 00 00 00 |....8...........| +00005cd0 04 00 f1 ff 42 00 00 00 00 00 00 00 00 00 00 00 |....B...........| +00005ce0 04 00 f1 ff 4b 00 00 00 00 00 00 00 00 00 00 00 |....K...........| +00005cf0 04 00 f1 ff 54 00 00 00 00 00 00 00 00 00 00 00 |....T...........| +00005d00 04 00 f1 ff 5d 00 00 00 00 00 00 00 00 00 00 00 |....]...........| +00005d10 04 00 f1 ff 67 00 00 00 00 00 00 00 00 00 00 00 |....g...........| +00005d20 04 00 f1 ff 70 00 00 00 00 00 00 00 00 00 00 00 |....p...........| +00005d30 04 00 f1 ff 76 00 00 00 2d 13 00 00 21 00 00 00 |....v...-...!...| +00005d40 12 00 01 00 7f 00 00 00 9e 13 00 00 00 00 00 00 |................| +00005d50 10 00 01 00 87 00 00 00 12 13 00 00 1b 00 00 00 |................| +00005d60 12 00 01 00 8e 00 00 00 91 16 00 00 72 00 00 00 |............r...| +00005d70 12 00 01 00 96 00 00 00 09 19 00 00 32 00 00 00 |............2...| +00005d80 12 00 01 00 9d 00 00 00 c6 13 00 00 00 00 00 00 |................| +00005d90 10 00 01 00 a4 00 00 00 f6 13 00 00 00 00 00 00 |................| +00005da0 10 00 01 00 aa 00 00 00 7b 13 00 00 1b 00 00 00 |........{.......| +00005db0 12 00 01 00 b1 00 00 00 3e 1a 00 00 22 00 00 00 |........>..."...| +00005dc0 12 00 01 00 b5 00 00 00 4f 12 00 00 75 00 00 00 |........O...u...| +00005dd0 12 00 01 00 bb 00 00 00 1c 14 00 00 75 02 00 00 |............u...| +00005de0 12 00 01 00 c2 00 00 00 f5 17 00 00 8a 00 00 00 |................| +00005df0 12 00 01 00 c9 00 00 00 3b 19 00 00 66 00 00 00 |........;...f...| +00005e00 12 00 01 00 88 00 00 00 be 13 00 00 00 00 00 00 |................| +00005e10 10 00 01 00 d1 00 00 00 ee 13 00 00 00 00 00 00 |................| +00005e20 10 00 01 00 d6 00 00 00 e5 12 00 00 2d 00 00 00 |............-...| +00005e30 12 00 01 00 de 00 00 00 ae 13 00 00 00 00 00 00 |................| +00005e40 10 00 01 00 e3 00 00 00 37 12 00 00 18 00 00 00 |........7.......| +00005e50 12 00 01 00 e8 00 00 00 4e 13 00 00 2d 00 00 00 |........N...-...| +00005e60 12 00 01 00 f0 00 00 00 0c 14 00 00 00 00 00 00 |................| +00005e70 10 00 01 00 f7 00 00 00 b6 13 00 00 00 00 00 00 |................| +00005e80 10 00 01 00 fc 00 00 00 de 13 00 00 00 00 00 00 |................| +00005e90 10 00 01 00 04 01 00 00 6c 17 00 00 89 00 00 00 |........l.......| +00005ea0 12 00 01 00 0c 01 00 00 a6 13 00 00 00 00 00 00 |................| +00005eb0 10 00 01 00 11 01 00 00 00 10 00 00 37 02 00 00 |............7...| +00005ec0 12 00 01 00 16 01 00 00 ce 13 00 00 00 00 00 00 |................| +00005ed0 10 00 01 00 1e 01 00 00 a1 19 00 00 9d 00 00 00 |................| +00005ee0 12 00 01 00 25 01 00 00 e6 13 00 00 00 00 00 00 |....%...........| +00005ef0 10 00 01 00 2d 01 00 00 7f 18 00 00 8a 00 00 00 |....-...........| +00005f00 12 00 01 00 34 01 00 00 c4 12 00 00 21 00 00 00 |....4.......!...| +00005f10 12 00 01 00 3d 01 00 00 d6 13 00 00 00 00 00 00 |....=...........| +00005f20 10 00 01 00 45 01 00 00 25 17 00 00 47 00 00 00 |....E...%...G...| +00005f30 12 00 01 00 5e 01 00 00 96 13 00 00 00 00 00 00 |....^...........| +00005f40 10 00 01 00 4c 01 00 00 03 17 00 00 22 00 00 00 |....L......."...| +00005f50 12 00 01 00 53 01 00 00 fe 13 00 00 00 00 00 00 |....S...........| +00005f60 10 00 01 00 59 01 00 00 06 14 00 00 00 00 00 00 |....Y...........| +00005f70 10 00 01 00 00 70 72 6f 67 41 42 43 2e 63 00 75 |.....progABC.c.u| +00005f80 6c 69 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 |libc.c.sprint.c.| +00005f90 73 74 72 32 69 6e 74 2e 63 00 73 74 72 6c 65 6e |str2int.c.strlen| +00005fa0 2e 63 00 63 76 74 64 65 63 2e 63 00 63 76 74 64 |.c.cvtdec.c.cvtd| +00005fb0 65 63 30 2e 63 00 63 76 74 68 65 78 2e 63 00 63 |ec0.c.cvthex.c.c| +00005fc0 76 74 6f 63 74 2e 63 00 63 76 74 75 6e 73 2e 63 |vtoct.c.cvtuns.c| +00005fd0 00 63 76 74 75 6e 73 30 2e 63 00 70 61 64 73 74 |.cvtuns0.c.padst| +00005fe0 72 2e 63 00 70 61 64 2e 63 00 73 77 72 69 74 65 |r.c.pad.c.swrite| +00005ff0 63 68 00 77 61 69 74 70 69 64 00 63 77 72 69 74 |ch.waitpid.cwrit| +00006000 65 00 73 74 72 32 69 6e 74 00 63 76 74 75 6e 73 |e.str2int.cvtuns| +00006010 00 67 65 74 70 69 64 00 73 6c 65 65 70 00 73 77 |.getpid.sleep.sw| +00006020 72 69 74 65 00 70 61 64 00 73 70 61 77 6e 00 73 |rite.pad.spawn.s| +00006030 70 72 69 6e 74 00 63 76 74 68 65 78 00 63 76 74 |print.cvthex.cvt| +00006040 75 6e 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 65 |uns0.kill.cwrite| +00006050 73 00 65 78 65 63 00 77 61 69 74 00 73 77 72 69 |s.exec.wait.swri| +00006060 74 65 73 00 5f 73 74 61 72 74 00 72 65 61 64 00 |tes._start.read.| +00006070 67 65 74 70 72 69 6f 00 63 76 74 64 65 63 30 00 |getprio.cvtdec0.| +00006080 66 6f 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 69 |fork.main.getppi| +00006090 64 00 70 61 64 73 74 72 00 73 65 74 70 72 69 6f |d.padstr.setprio| +000060a0 00 63 76 74 6f 63 74 00 63 77 72 69 74 65 63 68 |.cvtoct.cwritech| +000060b0 00 67 65 74 74 69 6d 65 00 63 76 74 64 65 63 00 |.gettime.cvtdec.| +000060c0 73 74 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 6b |strlen.bogus.fak| +000060d0 65 5f 65 78 69 74 00 00 2e 73 79 6d 74 61 62 00 |e_exit...symtab.| +000060e0 2e 73 74 72 74 61 62 00 2e 73 68 73 74 72 74 61 |.strtab..shstrta| +000060f0 62 00 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 00 |b..text..rodata.| +00006100 2e 64 61 74 61 00 2e 62 73 73 00 00 00 00 00 00 |.data..bss......| +00006110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00006130 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +00006140 00 10 00 00 74 00 00 00 60 0a 00 00 00 00 00 00 |....t...`.......| +00006150 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +00006160 01 00 00 00 02 00 00 00 60 1a 00 00 d4 0a 00 00 |........`.......| +00006170 f0 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +00006180 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +00006190 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +000061a0 00 00 00 00 01 00 00 00 00 00 00 00 2f 00 00 00 |............/...| +000061b0 08 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +000061c0 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +000061d0 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +000061e0 00 00 00 00 74 10 00 00 60 03 00 00 06 00 00 00 |....t...`.......| +000061f0 12 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +00006200 03 00 00 00 00 00 00 00 00 00 00 00 d4 13 00 00 |................| +00006210 63 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |c...............| +00006220 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +00006230 00 00 00 00 37 15 00 00 34 00 00 00 00 00 00 00 |....7...4.......| +00006240 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +00006250 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +00006260 02 00 03 00 01 00 00 00 9b 13 00 00 34 00 00 00 |............4...| +00006270 6c 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |l.......4. ...(.| +00006280 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +00006290 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +000062a0 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +000062b0 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +000062c0 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +000062d0 e5 53 51 81 ec a0 00 00 00 89 cb c7 45 f4 1e 00 |.SQ.........E...| +000062e0 00 00 c6 45 f3 32 8b 03 83 f8 02 74 1e 83 f8 03 |...E.2.....t....| +000062f0 75 2c 8b 43 04 83 c0 08 8b 00 83 ec 08 6a 0a 50 |u,.C.........j.P| +00006300 e8 df 05 00 00 83 c4 10 89 45 f4 8b 43 04 83 c0 |.........E..C...| +00006310 04 8b 00 0f b6 00 88 45 f3 e9 a4 00 00 00 83 ec |.......E........| +00006320 04 ff 33 68 f0 19 00 00 8d 85 60 ff ff ff 50 e8 |..3h......`...P.| +00006330 3b 03 00 00 83 c4 10 83 ec 0c 8d 85 60 ff ff ff |;...........`...| +00006340 50 e8 f2 01 00 00 83 c4 10 c7 45 ec 00 00 00 00 |P.........E.....| +00006350 eb 59 8b 03 8d 14 85 00 00 00 00 8b 43 04 01 d0 |.Y..........C...| +00006360 8b 00 85 c0 74 12 8b 03 8d 14 85 00 00 00 00 8b |....t...........| +00006370 43 04 01 d0 8b 00 eb 05 b8 07 1a 00 00 83 ec 04 |C...............| +00006380 50 68 0e 1a 00 00 8d 85 60 ff ff ff 50 e8 dd 02 |Ph......`...P...| +00006390 00 00 83 c4 10 83 ec 0c 8d 85 60 ff ff ff 50 e8 |..........`...P.| +000063a0 94 01 00 00 83 c4 10 83 45 ec 01 8b 45 ec 3b 03 |........E...E.;.| +000063b0 7e a0 83 ec 0c 68 12 1a 00 00 e8 79 01 00 00 83 |~....h.....y....| +000063c0 c4 10 0f be 45 f3 83 ec 0c 50 e8 b1 01 00 00 83 |....E....P......| +000063d0 c4 10 89 45 e0 83 7d e0 01 74 2e 0f be 45 f3 ff |...E..}..t...E..| +000063e0 75 e0 50 68 14 1a 00 00 8d 85 60 ff ff ff 50 e8 |u.Ph......`...P.| +000063f0 7b 02 00 00 83 c4 10 83 ec 0c 8d 85 60 ff ff ff |{...........`...| +00006400 50 e8 32 01 00 00 83 c4 10 c7 45 e8 00 00 00 00 |P.2.......E.....| +00006410 eb 61 c7 45 e4 00 00 00 00 eb 04 83 45 e4 01 81 |.a.E........E...| +00006420 7d e4 9f 25 26 00 7e f3 0f be 45 f3 83 ec 0c 50 |}..%&.~...E....P| +00006430 e8 4b 01 00 00 83 c4 10 89 45 e0 83 7d e0 01 74 |.K.......E..}..t| +00006440 2e 0f be 45 f3 ff 75 e0 50 68 31 1a 00 00 8d 85 |...E..u.Ph1.....| +00006450 60 ff ff ff 50 e8 15 02 00 00 83 c4 10 83 ec 0c |`...P...........| +00006460 8d 85 60 ff ff ff 50 e8 cc 00 00 00 83 c4 10 83 |..`...P.........| +00006470 45 e8 01 8b 45 e8 3b 45 f4 7c 97 b8 00 00 00 00 |E...E.;E.|......| +00006480 8d 65 f8 59 5b 5d 8d 61 fc c3 55 89 e5 83 ec 08 |.e.Y[].a..U.....| +00006490 83 ec 08 ff 75 08 6a 00 e8 54 01 00 00 83 c4 10 |....u.j..T......| +000064a0 c9 c3 55 89 e5 81 ec 18 01 00 00 e8 49 01 00 00 |..U.........I...| +000064b0 89 45 f4 83 7d f4 00 74 05 8b 45 f4 eb 57 e8 56 |.E..}..t..E..W.V| +000064c0 01 00 00 89 45 f4 83 ec 08 ff 75 0c ff 75 08 e8 |....E.....u..u..| +000064d0 2d 01 00 00 83 c4 10 ff 75 08 ff 75 f4 68 4e 1a |-.......u..u.hN.| +000064e0 00 00 8d 85 f4 fe ff ff 50 e8 81 01 00 00 83 c4 |........P.......| +000064f0 10 83 ec 0c 8d 85 f4 fe ff ff 50 e8 38 00 00 00 |..........P.8...| +00006500 83 c4 10 83 ec 0c 6a ff e8 dc 00 00 00 83 c4 10 |......j.........| +00006510 b8 00 00 00 00 c9 c3 55 89 e5 83 ec 18 8b 45 08 |.......U......E.| +00006520 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 00 e8 de |.E....j..E.Pj...| +00006530 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 ec |........U.......| +00006540 0c ff 75 08 e8 0d 04 00 00 83 c4 10 89 45 f4 8b |..u..........E..| +00006550 45 f4 83 ec 04 50 ff 75 08 6a 00 e8 b1 00 00 00 |E....P.u.j......| +00006560 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff 75 |.....U.........u| +00006570 0c ff 75 08 6a 00 e8 96 00 00 00 83 c4 10 c9 c3 |..u.j...........| +00006580 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 6a |U......E..E....j| +00006590 01 8d 45 f4 50 6a 01 e8 75 00 00 00 83 c4 10 c9 |..E.Pj..u.......| +000065a0 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 a4 03 |.U.........u....| +000065b0 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 ff |......E..E....P.| +000065c0 75 08 6a 01 e8 48 00 00 00 83 c4 10 c9 c3 55 89 |u.j..H........U.| +000065d0 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 01 e8 |........u..u.j..| +000065e0 2d 00 00 00 83 c4 10 c9 c3 b8 00 00 00 00 cd 80 |-...............| +000065f0 c3 b8 01 00 00 00 cd 80 c3 b8 02 00 00 00 cd 80 |................| +00006600 c3 b8 03 00 00 00 cd 80 c3 b8 04 00 00 00 cd 80 |................| +00006610 c3 b8 05 00 00 00 cd 80 c3 b8 06 00 00 00 cd 80 |................| +00006620 c3 b8 07 00 00 00 cd 80 c3 b8 08 00 00 00 cd 80 |................| +00006630 c3 b8 09 00 00 00 cd 80 c3 b8 0a 00 00 00 cd 80 |................| +00006640 c3 b8 0b 00 00 00 cd 80 c3 b8 0c 00 00 00 cd 80 |................| +00006650 c3 b8 ad 0b 00 00 cd 80 c3 50 e8 8a ff ff ff e8 |.........P......| +00006660 60 fc ff ff 83 ec 0c 50 e8 7c ff ff ff eb fe 55 |`......P.|.....U| +00006670 89 e5 83 ec 38 8d 45 0c 83 c0 04 89 45 f4 e9 3f |....8.E.....E..?| +00006680 02 00 00 80 7d f3 25 0f 85 26 02 00 00 c7 45 ec |....}.%..&....E.| +00006690 00 00 00 00 c7 45 e4 20 00 00 00 c7 45 e8 00 00 |.....E. ....E...| +000066a0 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +000066b0 f3 80 7d f3 2d 75 16 c7 45 ec 01 00 00 00 8b 45 |..}.-u..E......E| +000066c0 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 |..P..U.....E..}.| +000066d0 30 75 40 c7 45 e4 30 00 00 00 8b 45 0c 8d 50 01 |0u@.E.0....E..P.| +000066e0 89 55 0c 0f b6 00 88 45 f3 eb 28 8b 55 e8 89 d0 |.U.....E..(.U...| +000066f0 c1 e0 02 01 d0 01 c0 89 45 e8 0f be 45 f3 83 e8 |........E...E...| +00006700 30 01 45 e8 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |0.E..E..P..U....| +00006710 88 45 f3 80 7d f3 2f 7e 06 80 7d f3 39 7e cc 0f |.E..}./~..}.9~..| +00006720 be 45 f3 83 e8 63 83 f8 15 0f 87 93 01 00 00 8b |.E...c..........| +00006730 04 85 6c 1a 00 00 ff e0 8b 45 f4 8d 50 04 89 55 |..l......E..P..U| +00006740 f4 8b 00 88 45 f3 0f b6 45 f3 88 45 d0 c6 45 d1 |....E...E..E..E.| +00006750 00 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a 01 8d |.....u..u..u.j..| +00006760 45 d0 50 ff 75 08 e8 89 04 00 00 83 c4 20 89 45 |E.P.u........ .E| +00006770 08 e9 4c 01 00 00 8b 45 f4 8d 50 04 89 55 f4 8b |..L....E..P..U..| +00006780 00 83 ec 08 50 8d 45 d0 50 e8 ea 01 00 00 83 c4 |....P.E.P.......| +00006790 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 |..E.....u..u..u.| +000067a0 ff 75 e0 8d 45 d0 50 ff 75 08 e8 45 04 00 00 83 |.u..E.P.u..E....| +000067b0 c4 20 89 45 08 e9 08 01 00 00 8b 45 f4 8d 50 04 |. .E.......E..P.| +000067c0 89 55 f4 8b 00 89 45 dc 83 ec 08 ff 75 e4 ff 75 |.U....E.....u..u| +000067d0 ec ff 75 e8 6a ff ff 75 dc ff 75 08 e8 13 04 00 |..u.j..u..u.....| +000067e0 00 83 c4 20 89 45 08 e9 d6 00 00 00 8b 45 f4 8d |... .E.......E..| +000067f0 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 |P..U......P.E.P.| +00006800 44 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 |D.......E.....u.| +00006810 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 |.u..u..u..E.P.u.| +00006820 e8 cf 03 00 00 83 c4 20 89 45 08 e9 92 00 00 00 |....... .E......| +00006830 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d |.E..P..U......P.| +00006840 45 d0 50 e8 8a 02 00 00 83 c4 10 89 45 e0 83 ec |E.P.........E...| +00006850 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 |..u..u..u..u..E.| +00006860 50 ff 75 08 e8 8b 03 00 00 83 c4 20 89 45 08 eb |P.u........ .E..| +00006870 51 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 |Q.E..P..U......P| +00006880 8d 45 d0 50 e8 d3 02 00 00 83 c4 10 89 45 e0 83 |.E.P.........E..| +00006890 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 |...u..u..u..u..E| +000068a0 d0 50 ff 75 08 e8 4a 03 00 00 83 c4 20 89 45 08 |.P.u..J..... .E.| +000068b0 90 eb 0f 8b 45 08 8d 50 01 89 55 08 0f b6 55 f3 |....E..P..U...U.| +000068c0 88 10 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +000068d0 f3 80 7d f3 00 0f 85 a8 fd ff ff 8b 45 08 c6 00 |..}.........E...| +000068e0 00 90 c9 c3 55 89 e5 53 83 ec 14 8b 45 08 8b 4d |....U..S....E..M| +000068f0 0c bb 00 00 00 00 c6 45 eb 39 c7 45 f8 01 00 00 |.......E.9.E....| +00006900 00 0f b6 10 80 fa 2d 75 0a c7 45 f8 ff ff ff ff |......-u..E.....| +00006910 83 c0 01 83 f9 0a 74 2b 89 ca 83 c2 2f 88 55 eb |......t+..../.U.| +00006920 eb 21 0f b6 10 80 fa 2f 7e 20 0f b6 10 38 55 eb |.!...../~ ...8U.| +00006930 7c 18 0f af d9 0f b6 10 0f be d2 01 da 8d 5a d0 ||.............Z.| +00006940 83 c0 01 0f b6 10 84 d2 75 d8 89 d8 0f af 45 f8 |........u.....E.| +00006950 83 c4 14 5b 5d c3 55 89 e5 53 8b 55 08 bb 00 00 |...[].U..S.U....| +00006960 00 00 eb 03 83 c3 01 89 d0 8d 50 01 0f b6 00 84 |..........P.....| +00006970 c0 75 f1 89 d8 5b 5d c3 55 89 e5 83 ec 18 8b 45 |.u...[].U......E| +00006980 08 89 45 f4 83 7d 0c 00 79 0f 8b 45 f4 8d 50 01 |..E..}..y..E..P.| +00006990 89 55 f4 c6 00 2d f7 5d 0c 83 ec 08 ff 75 0c ff |.U...-.].....u..| +000069a0 75 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 |u..........E..E.| +000069b0 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 |....U..E.).....U| +000069c0 89 e5 83 ec 18 8b 4d 0c ba 67 66 66 66 89 c8 f7 |......M..gfff...| +000069d0 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 89 45 f4 |.........)....E.| +000069e0 83 7d f4 00 79 0e c7 45 f4 cc cc cc 0c c7 45 0c |.}..y..E......E.| +000069f0 08 00 00 00 83 7d f4 00 74 14 83 ec 08 ff 75 f4 |.....}..t.....u.| +00006a00 ff 75 08 e8 b7 ff ff ff 83 c4 10 89 45 08 8b 4d |.u..........E..M| +00006a10 0c ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 |..gfff..........| +00006a20 f8 1f 29 c2 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 |..)..........)..| +00006a30 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 89 |....H0.E..P..U..| +00006a40 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 ec 20 c7 45 |....E...U.... .E| +00006a50 e3 30 31 32 33 c7 45 e7 34 35 36 37 c7 45 eb 38 |.0123.E.4567.E.8| +00006a60 39 41 42 c7 45 ef 43 44 45 46 c6 45 f3 00 c7 45 |9AB.E.CDEF.E...E| +00006a70 fc 00 00 00 00 c7 45 f8 00 00 00 00 eb 43 8b 45 |......E......C.E| +00006a80 0c 25 00 00 00 f0 89 45 f4 83 7d fc 00 75 0c 83 |.%.....E..}..u..| +00006a90 7d f4 00 75 06 83 7d f8 07 75 1e 83 45 fc 01 c1 |}..u..}..u..E...| +00006aa0 6d f4 1c 8b 45 08 8d 50 01 89 55 08 8d 4d e3 8b |m...E..P..U..M..| +00006ab0 55 f4 01 ca 0f b6 12 88 10 c1 65 0c 04 83 45 f8 |U.........e...E.| +00006ac0 01 83 7d f8 07 7e b7 8b 45 08 c6 00 00 8b 45 fc |..}..~..E.....E.| +00006ad0 c9 c3 55 89 e5 83 ec 10 c7 45 f8 00 00 00 00 8b |..U......E......| +00006ae0 45 08 89 45 f4 8b 45 0c 25 00 00 00 c0 89 45 f0 |E..E..E.%.....E.| +00006af0 c1 6d f0 1e c7 45 fc 00 00 00 00 eb 47 83 7d fc |.m...E......G.}.| +00006b00 0a 74 0c 83 7d f0 00 75 06 83 7d f8 00 74 1e c7 |.t..}..u..}..t..| +00006b10 45 f8 01 00 00 00 83 65 f0 07 8b 45 f0 8d 48 30 |E......e...E..H0| +00006b20 8b 45 f4 8d 50 01 89 55 f4 89 ca 88 10 c1 65 0c |.E..P..U......e.| +00006b30 03 8b 45 0c 25 00 00 00 e0 89 45 f0 c1 6d f0 1d |..E.%.....E..m..| +00006b40 83 45 fc 01 83 7d fc 0a 7e b3 8b 45 f4 c6 00 00 |.E...}..~..E....| +00006b50 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 |.U..E.).....U...| +00006b60 ec 18 8b 45 08 89 45 f4 83 ec 08 ff 75 0c ff 75 |...E..E.....u..u| +00006b70 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 |..........E..E..| +00006b80 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 |...U..E.).....U.| +00006b90 e5 83 ec 18 8b 45 0c ba cd cc cc cc f7 e2 89 d0 |.....E..........| +00006ba0 c1 e8 03 89 45 f4 83 7d f4 00 74 15 8b 45 f4 83 |....E..}..t..E..| +00006bb0 ec 08 50 ff 75 08 e8 04 fe ff ff 83 c4 10 89 45 |..P.u..........E| +00006bc0 08 8b 4d 0c ba cd cc cc cc 89 c8 f7 e2 c1 ea 03 |..M.............| +00006bd0 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d |.........)......| +00006be0 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 8b |H0.E..P..U......| +00006bf0 45 08 c9 c3 55 89 e5 83 ec 18 83 7d 10 00 79 11 |E...U......}..y.| +00006c00 83 ec 0c ff 75 0c e8 4b fd ff ff 83 c4 10 89 45 |....u..K.......E| +00006c10 10 8b 45 14 2b 45 10 89 45 f0 83 7d f0 00 7e 1d |..E.+E..E..}..~.| +00006c20 83 7d 18 00 75 17 83 ec 04 ff 75 1c ff 75 f0 ff |.}..u.....u..u..| +00006c30 75 08 e8 5a 00 00 00 83 c4 10 89 45 08 c7 45 f4 |u..Z.......E..E.| +00006c40 00 00 00 00 eb 1b 8b 55 f4 8b 45 0c 8d 0c 02 8b |.......U..E.....| +00006c50 45 08 8d 50 01 89 55 08 0f b6 11 88 10 83 45 f4 |E..P..U.......E.| +00006c60 01 8b 45 f4 3b 45 10 7c dd 83 7d f0 00 7e 1d 83 |..E.;E.|..}..~..| +00006c70 7d 18 00 74 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 |}..t.....u..u..u| +00006c80 08 e8 0b 00 00 00 83 c4 10 89 45 08 8b 45 08 c9 |..........E..E..| +00006c90 c3 55 89 e5 eb 12 8b 45 08 8d 50 01 89 55 08 8b |.U.....E..P..U..| +00006ca0 55 10 88 10 83 6d 0c 01 83 7d 0c 00 7f e8 8b 45 |U....m...}.....E| +00006cb0 08 5d c3 00 6d 61 69 6e 32 3a 20 61 72 67 63 20 |.]..main2: argc | +00006cc0 25 64 2c 20 61 72 67 73 3a 20 00 28 6e 75 6c 6c |%d, args: .(null| +00006cd0 29 00 20 25 73 00 0a 00 3d 3d 20 25 63 2c 20 77 |). %s...== %c, w| +00006ce0 72 69 74 65 20 23 31 20 72 65 74 75 72 6e 65 64 |rite #1 returned| +00006cf0 20 25 64 0a 00 3d 3d 20 25 63 2c 20 77 72 69 74 | %d..== %c, writ| +00006d00 65 20 23 32 20 72 65 74 75 72 6e 65 64 20 25 64 |e #2 returned %d| +00006d10 0a 00 43 68 69 6c 64 20 25 64 20 65 78 65 63 28 |..Child %d exec(| +00006d20 29 20 23 25 75 20 66 61 69 6c 65 64 0a 00 00 00 |) #%u failed....| +00006d30 74 14 00 00 b2 14 00 00 fe 15 00 00 fe 15 00 00 |t...............| +00006d40 fe 15 00 00 fe 15 00 00 fe 15 00 00 fe 15 00 00 |................| +* +00006d60 6c 15 00 00 fe 15 00 00 fe 15 00 00 fe 15 00 00 |l...............| +00006d70 f6 14 00 00 fe 15 00 00 ad 15 00 00 fe 15 00 00 |................| +00006d80 fe 15 00 00 28 15 00 00 00 00 00 00 00 00 00 00 |....(...........| +00006d90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +000072d0 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +000072e0 03 00 01 00 00 00 00 00 f0 19 00 00 00 00 00 00 |................| +000072f0 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +00007300 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +00007310 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +00007320 04 00 f1 ff 0a 00 00 00 00 00 00 00 00 00 00 00 |................| +00007330 04 00 f1 ff 12 00 00 00 00 00 00 00 00 00 00 00 |................| +00007340 04 00 f1 ff 1b 00 00 00 00 00 00 00 00 00 00 00 |................| +00007350 04 00 f1 ff 25 00 00 00 00 00 00 00 00 00 00 00 |....%...........| +00007360 04 00 f1 ff 2e 00 00 00 00 00 00 00 00 00 00 00 |................| +00007370 04 00 f1 ff 37 00 00 00 00 00 00 00 00 00 00 00 |....7...........| +00007380 04 00 f1 ff 41 00 00 00 00 00 00 00 00 00 00 00 |....A...........| +00007390 04 00 f1 ff 4a 00 00 00 00 00 00 00 00 00 00 00 |....J...........| +000073a0 04 00 f1 ff 53 00 00 00 00 00 00 00 00 00 00 00 |....S...........| +000073b0 04 00 f1 ff 5c 00 00 00 00 00 00 00 00 00 00 00 |....\...........| +000073c0 04 00 f1 ff 66 00 00 00 00 00 00 00 00 00 00 00 |....f...........| +000073d0 04 00 f1 ff 6f 00 00 00 00 00 00 00 00 00 00 00 |....o...........| +000073e0 04 00 f1 ff 75 00 00 00 bc 12 00 00 21 00 00 00 |....u.......!...| +000073f0 12 00 01 00 7e 00 00 00 2d 13 00 00 00 00 00 00 |....~...-.......| +00007400 10 00 01 00 86 00 00 00 a1 12 00 00 1b 00 00 00 |................| +00007410 12 00 01 00 8d 00 00 00 20 16 00 00 72 00 00 00 |........ ...r...| +00007420 12 00 01 00 95 00 00 00 98 18 00 00 32 00 00 00 |............2...| +00007430 12 00 01 00 9c 00 00 00 55 13 00 00 00 00 00 00 |........U.......| +00007440 10 00 01 00 a3 00 00 00 85 13 00 00 00 00 00 00 |................| +00007450 10 00 01 00 a9 00 00 00 0a 13 00 00 1b 00 00 00 |................| +00007460 12 00 01 00 b0 00 00 00 cd 19 00 00 22 00 00 00 |............"...| +00007470 12 00 01 00 b4 00 00 00 de 11 00 00 75 00 00 00 |............u...| +00007480 12 00 01 00 ba 00 00 00 ab 13 00 00 75 02 00 00 |............u...| +00007490 12 00 01 00 c1 00 00 00 84 17 00 00 8a 00 00 00 |................| +000074a0 12 00 01 00 c8 00 00 00 ca 18 00 00 66 00 00 00 |............f...| +000074b0 12 00 01 00 87 00 00 00 4d 13 00 00 00 00 00 00 |........M.......| +000074c0 10 00 01 00 d0 00 00 00 7d 13 00 00 00 00 00 00 |........}.......| +000074d0 10 00 01 00 d5 00 00 00 74 12 00 00 2d 00 00 00 |........t...-...| +000074e0 12 00 01 00 dd 00 00 00 3d 13 00 00 00 00 00 00 |........=.......| +000074f0 10 00 01 00 e2 00 00 00 c6 11 00 00 18 00 00 00 |................| +00007500 12 00 01 00 e7 00 00 00 dd 12 00 00 2d 00 00 00 |............-...| +00007510 12 00 01 00 ef 00 00 00 9b 13 00 00 00 00 00 00 |................| +00007520 10 00 01 00 f6 00 00 00 45 13 00 00 00 00 00 00 |........E.......| +00007530 10 00 01 00 fb 00 00 00 6d 13 00 00 00 00 00 00 |........m.......| +00007540 10 00 01 00 03 01 00 00 fb 16 00 00 89 00 00 00 |................| +00007550 12 00 01 00 0b 01 00 00 35 13 00 00 00 00 00 00 |........5.......| +00007560 10 00 01 00 10 01 00 00 00 10 00 00 c6 01 00 00 |................| +00007570 12 00 01 00 15 01 00 00 5d 13 00 00 00 00 00 00 |........].......| +00007580 10 00 01 00 1d 01 00 00 30 19 00 00 9d 00 00 00 |........0.......| +00007590 12 00 01 00 24 01 00 00 75 13 00 00 00 00 00 00 |....$...u.......| +000075a0 10 00 01 00 2c 01 00 00 0e 18 00 00 8a 00 00 00 |....,...........| +000075b0 12 00 01 00 33 01 00 00 53 12 00 00 21 00 00 00 |....3...S...!...| +000075c0 12 00 01 00 3c 01 00 00 65 13 00 00 00 00 00 00 |....<...e.......| +000075d0 10 00 01 00 44 01 00 00 b4 16 00 00 47 00 00 00 |....D.......G...| +000075e0 12 00 01 00 5d 01 00 00 25 13 00 00 00 00 00 00 |....]...%.......| +000075f0 10 00 01 00 4b 01 00 00 92 16 00 00 22 00 00 00 |....K......."...| +00007600 12 00 01 00 52 01 00 00 8d 13 00 00 00 00 00 00 |....R...........| +00007610 10 00 01 00 58 01 00 00 95 13 00 00 00 00 00 00 |....X...........| +00007620 10 00 01 00 00 70 72 6f 67 44 45 2e 63 00 75 6c |.....progDE.c.ul| +00007630 69 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 |ibc.c.sprint.c.s| +00007640 74 72 32 69 6e 74 2e 63 00 73 74 72 6c 65 6e 2e |tr2int.c.strlen.| +00007650 63 00 63 76 74 64 65 63 2e 63 00 63 76 74 64 65 |c.cvtdec.c.cvtde| +00007660 63 30 2e 63 00 63 76 74 68 65 78 2e 63 00 63 76 |c0.c.cvthex.c.cv| +00007670 74 6f 63 74 2e 63 00 63 76 74 75 6e 73 2e 63 00 |toct.c.cvtuns.c.| +00007680 63 76 74 75 6e 73 30 2e 63 00 70 61 64 73 74 72 |cvtuns0.c.padstr| +00007690 2e 63 00 70 61 64 2e 63 00 73 77 72 69 74 65 63 |.c.pad.c.swritec| +000076a0 68 00 77 61 69 74 70 69 64 00 63 77 72 69 74 65 |h.waitpid.cwrite| +000076b0 00 73 74 72 32 69 6e 74 00 63 76 74 75 6e 73 00 |.str2int.cvtuns.| +000076c0 67 65 74 70 69 64 00 73 6c 65 65 70 00 73 77 72 |getpid.sleep.swr| +000076d0 69 74 65 00 70 61 64 00 73 70 61 77 6e 00 73 70 |ite.pad.spawn.sp| +000076e0 72 69 6e 74 00 63 76 74 68 65 78 00 63 76 74 75 |rint.cvthex.cvtu| +000076f0 6e 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 65 73 |ns0.kill.cwrites| +00007700 00 65 78 65 63 00 77 61 69 74 00 73 77 72 69 74 |.exec.wait.swrit| +00007710 65 73 00 5f 73 74 61 72 74 00 72 65 61 64 00 67 |es._start.read.g| +00007720 65 74 70 72 69 6f 00 63 76 74 64 65 63 30 00 66 |etprio.cvtdec0.f| +00007730 6f 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 69 64 |ork.main.getppid| +00007740 00 70 61 64 73 74 72 00 73 65 74 70 72 69 6f 00 |.padstr.setprio.| +00007750 63 76 74 6f 63 74 00 63 77 72 69 74 65 63 68 00 |cvtoct.cwritech.| +00007760 67 65 74 74 69 6d 65 00 63 76 74 64 65 63 00 73 |gettime.cvtdec.s| +00007770 74 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 6b 65 |trlen.bogus.fake| +00007780 5f 65 78 69 74 00 00 2e 73 79 6d 74 61 62 00 2e |_exit...symtab..| +00007790 73 74 72 74 61 62 00 2e 73 68 73 74 72 74 61 62 |strtab..shstrtab| +000077a0 00 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 00 2e |..text..rodata..| +000077b0 64 61 74 61 00 2e 62 73 73 00 00 00 00 00 00 00 |data..bss.......| +000077c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +000077e0 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +000077f0 00 10 00 00 74 00 00 00 ef 09 00 00 00 00 00 00 |....t...........| +00007800 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +00007810 01 00 00 00 02 00 00 00 f0 19 00 00 64 0a 00 00 |............d...| +00007820 d4 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +00007830 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +00007840 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +00007850 00 00 00 00 01 00 00 00 00 00 00 00 2f 00 00 00 |............/...| +00007860 08 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +00007870 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +00007880 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +00007890 00 00 00 00 74 10 00 00 60 03 00 00 06 00 00 00 |....t...`.......| +000078a0 12 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +000078b0 03 00 00 00 00 00 00 00 00 00 00 00 d4 13 00 00 |................| +000078c0 62 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |b...............| +000078d0 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +000078e0 00 00 00 00 36 15 00 00 34 00 00 00 00 00 00 00 |....6...4.......| +000078f0 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +00007900 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +00007910 02 00 03 00 01 00 00 00 b3 13 00 00 34 00 00 00 |............4...| +00007920 6c 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |l.......4. ...(.| +00007930 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +00007940 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +00007950 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +00007960 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +00007970 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +00007980 e5 53 51 81 ec a0 00 00 00 89 cb c6 45 e3 33 c7 |.SQ.........E.3.| +00007990 45 f4 0a 00 00 00 c7 45 f0 1e 00 00 00 8b 03 83 |E......E........| +000079a0 f8 03 74 25 83 f8 04 74 07 83 f8 02 74 34 eb 45 |..t%...t....t4.E| +000079b0 8b 43 04 83 c0 0c 8b 00 83 ec 08 6a 0a 50 e8 e9 |.C.........j.P..| +000079c0 05 00 00 83 c4 10 89 45 f4 8b 43 04 83 c0 08 8b |.......E..C.....| +000079d0 00 83 ec 08 6a 0a 50 e8 d0 05 00 00 83 c4 10 89 |....j.P.........| +000079e0 45 f0 8b 43 04 83 c0 04 8b 00 0f b6 00 88 45 e3 |E..C..........E.| +000079f0 e9 a4 00 00 00 83 ec 04 ff 33 68 08 1a 00 00 8d |.........3h.....| +00007a00 85 63 ff ff ff 50 e8 2c 03 00 00 83 c4 10 83 ec |.c...P.,........| +00007a10 0c 8d 85 63 ff ff ff 50 e8 e3 01 00 00 83 c4 10 |...c...P........| +00007a20 c7 45 ec 00 00 00 00 eb 59 8b 03 8d 14 85 00 00 |.E......Y.......| +00007a30 00 00 8b 43 04 01 d0 8b 00 85 c0 74 12 8b 03 8d |...C.......t....| +00007a40 14 85 00 00 00 00 8b 43 04 01 d0 8b 00 eb 05 b8 |.......C........| +00007a50 1f 1a 00 00 83 ec 04 50 68 26 1a 00 00 8d 85 63 |.......Ph&.....c| +00007a60 ff ff ff 50 e8 ce 02 00 00 83 c4 10 83 ec 0c 8d |...P............| +00007a70 85 63 ff ff ff 50 e8 85 01 00 00 83 c4 10 83 45 |.c...P.........E| +00007a80 ec 01 8b 45 ec 3b 03 7e a0 83 ec 0c 68 2a 1a 00 |...E.;.~....h*..| +00007a90 00 e8 6a 01 00 00 83 c4 10 0f b6 45 e3 0f be c0 |..j........E....| +00007aa0 83 ec 0c 50 e8 9f 01 00 00 83 c4 10 89 45 e4 83 |...P.........E..| +00007ab0 7d e4 01 74 31 0f b6 45 e3 0f be c0 ff 75 e4 50 |}..t1..E.....u.P| +00007ac0 68 2c 1a 00 00 8d 85 63 ff ff ff 50 e8 66 02 00 |h,.....c...P.f..| +00007ad0 00 83 c4 10 83 ec 0c 8d 85 63 ff ff ff 50 e8 1d |.........c...P..| +00007ae0 01 00 00 83 c4 10 83 ec 04 6a 01 8d 45 e3 50 6a |.........j..E.Pj| +00007af0 01 e8 e3 01 00 00 83 c4 10 c7 45 e8 00 00 00 00 |..........E.....| +00007b00 eb 2c 8b 45 f4 69 c0 e8 03 00 00 83 ec 0c 50 e8 |.,.E.i........P.| +00007b10 fd 01 00 00 83 c4 10 83 ec 04 6a 01 8d 45 e3 50 |..........j..E.P| +00007b20 6a 01 e8 b2 01 00 00 83 c4 10 83 45 e8 01 8b 45 |j..........E...E| +00007b30 e8 3b 45 f0 7c cc 83 ec 0c 6a 00 e8 71 01 00 00 |.;E.|....j..q...| +00007b40 83 c4 10 b8 2a 00 00 00 8d 65 f8 59 5b 5d 8d 61 |....*....e.Y[].a| +00007b50 fc c3 55 89 e5 83 ec 08 83 ec 08 ff 75 08 6a 00 |..U.........u.j.| +00007b60 e8 54 01 00 00 83 c4 10 c9 c3 55 89 e5 81 ec 18 |.T........U.....| +00007b70 01 00 00 e8 49 01 00 00 89 45 f4 83 7d f4 00 74 |....I....E..}..t| +00007b80 05 8b 45 f4 eb 57 e8 56 01 00 00 89 45 f4 83 ec |..E..W.V....E...| +00007b90 08 ff 75 0c ff 75 08 e8 2d 01 00 00 83 c4 10 ff |..u..u..-.......| +00007ba0 75 08 ff 75 f4 68 4a 1a 00 00 8d 85 f4 fe ff ff |u..u.hJ.........| +00007bb0 50 e8 81 01 00 00 83 c4 10 83 ec 0c 8d 85 f4 fe |P...............| +00007bc0 ff ff 50 e8 38 00 00 00 83 c4 10 83 ec 0c 6a ff |..P.8.........j.| +00007bd0 e8 dc 00 00 00 83 c4 10 b8 00 00 00 00 c9 c3 55 |...............U| +00007be0 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 6a 01 |......E..E....j.| +00007bf0 8d 45 f4 50 6a 00 e8 de 00 00 00 83 c4 10 c9 c3 |.E.Pj...........| +00007c00 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 0d 04 00 |U.........u.....| +00007c10 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 ff 75 |.....E..E....P.u| +00007c20 08 6a 00 e8 b1 00 00 00 83 c4 10 c9 c3 55 89 e5 |.j...........U..| +00007c30 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 00 e8 96 |.......u..u.j...| +00007c40 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 8b 45 |........U......E| +00007c50 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 01 e8 |..E....j..E.Pj..| +00007c60 75 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 |u........U......| +00007c70 ec 0c ff 75 08 e8 a4 03 00 00 83 c4 10 89 45 f4 |...u..........E.| +00007c80 8b 45 f4 83 ec 04 50 ff 75 08 6a 01 e8 48 00 00 |.E....P.u.j..H..| +00007c90 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff |......U.........| +00007ca0 75 0c ff 75 08 6a 01 e8 2d 00 00 00 83 c4 10 c9 |u..u.j..-.......| +00007cb0 c3 b8 00 00 00 00 cd 80 c3 b8 01 00 00 00 cd 80 |................| +00007cc0 c3 b8 02 00 00 00 cd 80 c3 b8 03 00 00 00 cd 80 |................| +00007cd0 c3 b8 04 00 00 00 cd 80 c3 b8 05 00 00 00 cd 80 |................| +00007ce0 c3 b8 06 00 00 00 cd 80 c3 b8 07 00 00 00 cd 80 |................| +00007cf0 c3 b8 08 00 00 00 cd 80 c3 b8 09 00 00 00 cd 80 |................| +00007d00 c3 b8 0a 00 00 00 cd 80 c3 b8 0b 00 00 00 cd 80 |................| +00007d10 c3 b8 0c 00 00 00 cd 80 c3 b8 ad 0b 00 00 cd 80 |................| +00007d20 c3 50 e8 8a ff ff ff e8 48 fc ff ff 83 ec 0c 50 |.P......H......P| +00007d30 e8 7c ff ff ff eb fe 55 89 e5 83 ec 38 8d 45 0c |.|.....U....8.E.| +00007d40 83 c0 04 89 45 f4 e9 3f 02 00 00 80 7d f3 25 0f |....E..?....}.%.| +00007d50 85 26 02 00 00 c7 45 ec 00 00 00 00 c7 45 e4 20 |.&....E......E. | +00007d60 00 00 00 c7 45 e8 00 00 00 00 8b 45 0c 8d 50 01 |....E......E..P.| +00007d70 89 55 0c 0f b6 00 88 45 f3 80 7d f3 2d 75 16 c7 |.U.....E..}.-u..| +00007d80 45 ec 01 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f |E......E..P..U..| +00007d90 b6 00 88 45 f3 80 7d f3 30 75 40 c7 45 e4 30 00 |...E..}.0u@.E.0.| +00007da0 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +00007db0 f3 eb 28 8b 55 e8 89 d0 c1 e0 02 01 d0 01 c0 89 |..(.U...........| +00007dc0 45 e8 0f be 45 f3 83 e8 30 01 45 e8 8b 45 0c 8d |E...E...0.E..E..| +00007dd0 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 2f 7e |P..U.....E..}./~| +00007de0 06 80 7d f3 39 7e cc 0f be 45 f3 83 e8 63 83 f8 |..}.9~...E...c..| +00007df0 15 0f 87 93 01 00 00 8b 04 85 68 1a 00 00 ff e0 |..........h.....| +00007e00 8b 45 f4 8d 50 04 89 55 f4 8b 00 88 45 f3 0f b6 |.E..P..U....E...| +00007e10 45 f3 88 45 d0 c6 45 d1 00 83 ec 08 ff 75 e4 ff |E..E..E......u..| +00007e20 75 ec ff 75 e8 6a 01 8d 45 d0 50 ff 75 08 e8 89 |u..u.j..E.P.u...| +00007e30 04 00 00 83 c4 20 89 45 08 e9 4c 01 00 00 8b 45 |..... .E..L....E| +00007e40 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 |..P..U......P.E.| +00007e50 50 e8 ea 01 00 00 83 c4 10 89 45 e0 83 ec 08 ff |P.........E.....| +00007e60 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff |u..u..u..u..E.P.| +00007e70 75 08 e8 45 04 00 00 83 c4 20 89 45 08 e9 08 01 |u..E..... .E....| +00007e80 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 89 45 dc |...E..P..U....E.| +00007e90 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a ff ff 75 |....u..u..u.j..u| +00007ea0 dc ff 75 08 e8 13 04 00 00 83 c4 20 89 45 08 e9 |..u........ .E..| +00007eb0 d6 00 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 |.....E..P..U....| +00007ec0 ec 08 50 8d 45 d0 50 e8 44 02 00 00 83 c4 10 89 |..P.E.P.D.......| +00007ed0 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 |E.....u..u..u..u| +00007ee0 e0 8d 45 d0 50 ff 75 08 e8 cf 03 00 00 83 c4 20 |..E.P.u........ | +00007ef0 89 45 08 e9 92 00 00 00 8b 45 f4 8d 50 04 89 55 |.E.......E..P..U| +00007f00 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 8a 02 00 00 |......P.E.P.....| +00007f10 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff |....E.....u..u..| +00007f20 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 8b 03 00 |u..u..E.P.u.....| +00007f30 00 83 c4 20 89 45 08 eb 51 8b 45 f4 8d 50 04 89 |... .E..Q.E..P..| +00007f40 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 d3 02 00 |U......P.E.P....| +00007f50 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec |.....E.....u..u.| +00007f60 ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 4a 03 |.u..u..E.P.u..J.| +00007f70 00 00 83 c4 20 89 45 08 90 eb 0f 8b 45 08 8d 50 |.... .E.....E..P| +00007f80 01 89 55 08 0f b6 55 f3 88 10 8b 45 0c 8d 50 01 |..U...U....E..P.| +00007f90 89 55 0c 0f b6 00 88 45 f3 80 7d f3 00 0f 85 a8 |.U.....E..}.....| +00007fa0 fd ff ff 8b 45 08 c6 00 00 90 c9 c3 55 89 e5 53 |....E.......U..S| +00007fb0 83 ec 14 8b 45 08 8b 4d 0c bb 00 00 00 00 c6 45 |....E..M.......E| +00007fc0 eb 39 c7 45 f8 01 00 00 00 0f b6 10 80 fa 2d 75 |.9.E..........-u| +00007fd0 0a c7 45 f8 ff ff ff ff 83 c0 01 83 f9 0a 74 2b |..E...........t+| +00007fe0 89 ca 83 c2 2f 88 55 eb eb 21 0f b6 10 80 fa 2f |..../.U..!...../| +00007ff0 7e 20 0f b6 10 38 55 eb 7c 18 0f af d9 0f b6 10 |~ ...8U.|.......| +00008000 0f be d2 01 da 8d 5a d0 83 c0 01 0f b6 10 84 d2 |......Z.........| +00008010 75 d8 89 d8 0f af 45 f8 83 c4 14 5b 5d c3 55 89 |u.....E....[].U.| +00008020 e5 53 8b 55 08 bb 00 00 00 00 eb 03 83 c3 01 89 |.S.U............| +00008030 d0 8d 50 01 0f b6 00 84 c0 75 f1 89 d8 5b 5d c3 |..P......u...[].| +00008040 55 89 e5 83 ec 18 8b 45 08 89 45 f4 83 7d 0c 00 |U......E..E..}..| +00008050 79 0f 8b 45 f4 8d 50 01 89 55 f4 c6 00 2d f7 5d |y..E..P..U...-.]| +00008060 0c 83 ec 08 ff 75 0c ff 75 f4 e8 18 00 00 00 83 |.....u..u.......| +00008070 c4 10 89 45 f4 8b 45 f4 c6 00 00 8b 55 f4 8b 45 |...E..E.....U..E| +00008080 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b 4d 0c |.).....U......M.| +00008090 ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 f8 |.gfff...........| +000080a0 1f 29 c2 89 d0 89 45 f4 83 7d f4 00 79 0e c7 45 |.)....E..}..y..E| +000080b0 f4 cc cc cc 0c c7 45 0c 08 00 00 00 83 7d f4 00 |......E......}..| +000080c0 74 14 83 ec 08 ff 75 f4 ff 75 08 e8 b7 ff ff ff |t.....u..u......| +000080d0 83 c4 10 89 45 08 8b 4d 0c ba 67 66 66 66 89 c8 |....E..M..gfff..| +000080e0 f7 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 c1 e0 |..........).....| +000080f0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d 48 30 8b 45 |.....)......H0.E| +00008100 08 8d 50 01 89 55 08 89 ca 88 10 8b 45 08 c9 c3 |..P..U......E...| +00008110 55 89 e5 83 ec 20 c7 45 e3 30 31 32 33 c7 45 e7 |U.... .E.0123.E.| +00008120 34 35 36 37 c7 45 eb 38 39 41 42 c7 45 ef 43 44 |4567.E.89AB.E.CD| +00008130 45 46 c6 45 f3 00 c7 45 fc 00 00 00 00 c7 45 f8 |EF.E...E......E.| +00008140 00 00 00 00 eb 43 8b 45 0c 25 00 00 00 f0 89 45 |.....C.E.%.....E| +00008150 f4 83 7d fc 00 75 0c 83 7d f4 00 75 06 83 7d f8 |..}..u..}..u..}.| +00008160 07 75 1e 83 45 fc 01 c1 6d f4 1c 8b 45 08 8d 50 |.u..E...m...E..P| +00008170 01 89 55 08 8d 4d e3 8b 55 f4 01 ca 0f b6 12 88 |..U..M..U.......| +00008180 10 c1 65 0c 04 83 45 f8 01 83 7d f8 07 7e b7 8b |..e...E...}..~..| +00008190 45 08 c6 00 00 8b 45 fc c9 c3 55 89 e5 83 ec 10 |E.....E...U.....| +000081a0 c7 45 f8 00 00 00 00 8b 45 08 89 45 f4 8b 45 0c |.E......E..E..E.| +000081b0 25 00 00 00 c0 89 45 f0 c1 6d f0 1e c7 45 fc 00 |%.....E..m...E..| +000081c0 00 00 00 eb 47 83 7d fc 0a 74 0c 83 7d f0 00 75 |....G.}..t..}..u| +000081d0 06 83 7d f8 00 74 1e c7 45 f8 01 00 00 00 83 65 |..}..t..E......e| +000081e0 f0 07 8b 45 f0 8d 48 30 8b 45 f4 8d 50 01 89 55 |...E..H0.E..P..U| +000081f0 f4 89 ca 88 10 c1 65 0c 03 8b 45 0c 25 00 00 00 |......e...E.%...| +00008200 e0 89 45 f0 c1 6d f0 1d 83 45 fc 01 83 7d fc 0a |..E..m...E...}..| +00008210 7e b3 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 |~..E.....U..E.).| +00008220 89 d0 c9 c3 55 89 e5 83 ec 18 8b 45 08 89 45 f4 |....U......E..E.| +00008230 83 ec 08 ff 75 0c ff 75 f4 e8 18 00 00 00 83 c4 |....u..u........| +00008240 10 89 45 f4 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 |..E..E.....U..E.| +00008250 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b 45 0c ba |).....U......E..| +00008260 cd cc cc cc f7 e2 89 d0 c1 e8 03 89 45 f4 83 7d |............E..}| +00008270 f4 00 74 15 8b 45 f4 83 ec 08 50 ff 75 08 e8 04 |..t..E....P.u...| +00008280 fe ff ff 83 c4 10 89 45 08 8b 4d 0c ba cd cc cc |.......E..M.....| +00008290 cc 89 c8 f7 e2 c1 ea 03 89 d0 c1 e0 02 01 d0 01 |................| +000082a0 c0 29 c1 89 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 |.)......H0.E..P.| +000082b0 89 55 08 89 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 |.U......E...U...| +000082c0 ec 18 83 7d 10 00 79 11 83 ec 0c ff 75 0c e8 4b |...}..y.....u..K| +000082d0 fd ff ff 83 c4 10 89 45 10 8b 45 14 2b 45 10 89 |.......E..E.+E..| +000082e0 45 f0 83 7d f0 00 7e 1d 83 7d 18 00 75 17 83 ec |E..}..~..}..u...| +000082f0 04 ff 75 1c ff 75 f0 ff 75 08 e8 5a 00 00 00 83 |..u..u..u..Z....| +00008300 c4 10 89 45 08 c7 45 f4 00 00 00 00 eb 1b 8b 55 |...E..E........U| +00008310 f4 8b 45 0c 8d 0c 02 8b 45 08 8d 50 01 89 55 08 |..E.....E..P..U.| +00008320 0f b6 11 88 10 83 45 f4 01 8b 45 f4 3b 45 10 7c |......E...E.;E.|| +00008330 dd 83 7d f0 00 7e 1d 83 7d 18 00 74 17 83 ec 04 |..}..~..}..t....| +00008340 ff 75 1c ff 75 f0 ff 75 08 e8 0b 00 00 00 83 c4 |.u..u..u........| +00008350 10 89 45 08 8b 45 08 c9 c3 55 89 e5 eb 12 8b 45 |..E..E...U.....E| +00008360 08 8d 50 01 89 55 08 8b 55 10 88 10 83 6d 0c 01 |..P..U..U....m..| +00008370 83 7d 0c 00 7f e8 8b 45 08 5d c3 00 6d 61 69 6e |.}.....E.]..main| +00008380 33 3a 20 61 72 67 63 20 25 64 2c 20 61 72 67 73 |3: argc %d, args| +00008390 3a 20 00 28 6e 75 6c 6c 29 00 20 25 73 00 0a 00 |: .(null). %s...| +000083a0 3d 3d 3d 20 25 63 2c 20 77 72 69 74 65 20 23 31 |=== %c, write #1| +000083b0 20 72 65 74 75 72 6e 65 64 20 25 64 0a 00 43 68 | returned %d..Ch| +000083c0 69 6c 64 20 25 64 20 65 78 65 63 28 29 20 23 25 |ild %d exec() #%| +000083d0 75 20 66 61 69 6c 65 64 0a 00 00 00 8c 14 00 00 |u failed........| +000083e0 ca 14 00 00 16 16 00 00 16 16 00 00 16 16 00 00 |................| +000083f0 16 16 00 00 16 16 00 00 16 16 00 00 16 16 00 00 |................| +00008400 16 16 00 00 16 16 00 00 16 16 00 00 84 15 00 00 |................| +00008410 16 16 00 00 16 16 00 00 16 16 00 00 0e 15 00 00 |................| +00008420 16 16 00 00 c5 15 00 00 16 16 00 00 16 16 00 00 |................| +00008430 40 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@...............| +00008440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00008980 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +00008990 03 00 01 00 00 00 00 00 08 1a 00 00 00 00 00 00 |................| +000089a0 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +000089b0 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +000089c0 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +000089d0 04 00 f1 ff 0a 00 00 00 00 00 00 00 00 00 00 00 |................| +000089e0 04 00 f1 ff 12 00 00 00 00 00 00 00 00 00 00 00 |................| +000089f0 04 00 f1 ff 1b 00 00 00 00 00 00 00 00 00 00 00 |................| +00008a00 04 00 f1 ff 25 00 00 00 00 00 00 00 00 00 00 00 |....%...........| +00008a10 04 00 f1 ff 2e 00 00 00 00 00 00 00 00 00 00 00 |................| +00008a20 04 00 f1 ff 37 00 00 00 00 00 00 00 00 00 00 00 |....7...........| +00008a30 04 00 f1 ff 41 00 00 00 00 00 00 00 00 00 00 00 |....A...........| +00008a40 04 00 f1 ff 4a 00 00 00 00 00 00 00 00 00 00 00 |....J...........| +00008a50 04 00 f1 ff 53 00 00 00 00 00 00 00 00 00 00 00 |....S...........| +00008a60 04 00 f1 ff 5c 00 00 00 00 00 00 00 00 00 00 00 |....\...........| +00008a70 04 00 f1 ff 66 00 00 00 00 00 00 00 00 00 00 00 |....f...........| +00008a80 04 00 f1 ff 6f 00 00 00 00 00 00 00 00 00 00 00 |....o...........| +00008a90 04 00 f1 ff 75 00 00 00 d4 12 00 00 21 00 00 00 |....u.......!...| +00008aa0 12 00 01 00 7e 00 00 00 45 13 00 00 00 00 00 00 |....~...E.......| +00008ab0 10 00 01 00 86 00 00 00 b9 12 00 00 1b 00 00 00 |................| +00008ac0 12 00 01 00 8d 00 00 00 38 16 00 00 72 00 00 00 |........8...r...| +00008ad0 12 00 01 00 95 00 00 00 b0 18 00 00 32 00 00 00 |............2...| +00008ae0 12 00 01 00 9c 00 00 00 6d 13 00 00 00 00 00 00 |........m.......| +00008af0 10 00 01 00 a3 00 00 00 9d 13 00 00 00 00 00 00 |................| +00008b00 10 00 01 00 a9 00 00 00 22 13 00 00 1b 00 00 00 |........".......| +00008b10 12 00 01 00 b0 00 00 00 e5 19 00 00 22 00 00 00 |............"...| +00008b20 12 00 01 00 b4 00 00 00 f6 11 00 00 75 00 00 00 |............u...| +00008b30 12 00 01 00 ba 00 00 00 c3 13 00 00 75 02 00 00 |............u...| +00008b40 12 00 01 00 c1 00 00 00 9c 17 00 00 8a 00 00 00 |................| +00008b50 12 00 01 00 c8 00 00 00 e2 18 00 00 66 00 00 00 |............f...| +00008b60 12 00 01 00 87 00 00 00 65 13 00 00 00 00 00 00 |........e.......| +00008b70 10 00 01 00 d0 00 00 00 95 13 00 00 00 00 00 00 |................| +00008b80 10 00 01 00 d5 00 00 00 8c 12 00 00 2d 00 00 00 |............-...| +00008b90 12 00 01 00 dd 00 00 00 55 13 00 00 00 00 00 00 |........U.......| +00008ba0 10 00 01 00 e2 00 00 00 de 11 00 00 18 00 00 00 |................| +00008bb0 12 00 01 00 e7 00 00 00 f5 12 00 00 2d 00 00 00 |............-...| +00008bc0 12 00 01 00 ef 00 00 00 b3 13 00 00 00 00 00 00 |................| +00008bd0 10 00 01 00 f6 00 00 00 5d 13 00 00 00 00 00 00 |........].......| +00008be0 10 00 01 00 fb 00 00 00 85 13 00 00 00 00 00 00 |................| +00008bf0 10 00 01 00 03 01 00 00 13 17 00 00 89 00 00 00 |................| +00008c00 12 00 01 00 0b 01 00 00 4d 13 00 00 00 00 00 00 |........M.......| +00008c10 10 00 01 00 10 01 00 00 00 10 00 00 de 01 00 00 |................| +00008c20 12 00 01 00 15 01 00 00 75 13 00 00 00 00 00 00 |........u.......| +00008c30 10 00 01 00 1d 01 00 00 48 19 00 00 9d 00 00 00 |........H.......| +00008c40 12 00 01 00 24 01 00 00 8d 13 00 00 00 00 00 00 |....$...........| +00008c50 10 00 01 00 2c 01 00 00 26 18 00 00 8a 00 00 00 |....,...&.......| +00008c60 12 00 01 00 33 01 00 00 6b 12 00 00 21 00 00 00 |....3...k...!...| +00008c70 12 00 01 00 3c 01 00 00 7d 13 00 00 00 00 00 00 |....<...}.......| +00008c80 10 00 01 00 44 01 00 00 cc 16 00 00 47 00 00 00 |....D.......G...| +00008c90 12 00 01 00 5d 01 00 00 3d 13 00 00 00 00 00 00 |....]...=.......| +00008ca0 10 00 01 00 4b 01 00 00 aa 16 00 00 22 00 00 00 |....K......."...| +00008cb0 12 00 01 00 52 01 00 00 a5 13 00 00 00 00 00 00 |....R...........| +00008cc0 10 00 01 00 58 01 00 00 ad 13 00 00 00 00 00 00 |....X...........| +00008cd0 10 00 01 00 00 70 72 6f 67 46 47 2e 63 00 75 6c |.....progFG.c.ul| +00008ce0 69 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 |ibc.c.sprint.c.s| +00008cf0 74 72 32 69 6e 74 2e 63 00 73 74 72 6c 65 6e 2e |tr2int.c.strlen.| +00008d00 63 00 63 76 74 64 65 63 2e 63 00 63 76 74 64 65 |c.cvtdec.c.cvtde| +00008d10 63 30 2e 63 00 63 76 74 68 65 78 2e 63 00 63 76 |c0.c.cvthex.c.cv| +00008d20 74 6f 63 74 2e 63 00 63 76 74 75 6e 73 2e 63 00 |toct.c.cvtuns.c.| +00008d30 63 76 74 75 6e 73 30 2e 63 00 70 61 64 73 74 72 |cvtuns0.c.padstr| +00008d40 2e 63 00 70 61 64 2e 63 00 73 77 72 69 74 65 63 |.c.pad.c.swritec| +00008d50 68 00 77 61 69 74 70 69 64 00 63 77 72 69 74 65 |h.waitpid.cwrite| +00008d60 00 73 74 72 32 69 6e 74 00 63 76 74 75 6e 73 00 |.str2int.cvtuns.| +00008d70 67 65 74 70 69 64 00 73 6c 65 65 70 00 73 77 72 |getpid.sleep.swr| +00008d80 69 74 65 00 70 61 64 00 73 70 61 77 6e 00 73 70 |ite.pad.spawn.sp| +00008d90 72 69 6e 74 00 63 76 74 68 65 78 00 63 76 74 75 |rint.cvthex.cvtu| +00008da0 6e 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 65 73 |ns0.kill.cwrites| +00008db0 00 65 78 65 63 00 77 61 69 74 00 73 77 72 69 74 |.exec.wait.swrit| +00008dc0 65 73 00 5f 73 74 61 72 74 00 72 65 61 64 00 67 |es._start.read.g| +00008dd0 65 74 70 72 69 6f 00 63 76 74 64 65 63 30 00 66 |etprio.cvtdec0.f| +00008de0 6f 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 69 64 |ork.main.getppid| +00008df0 00 70 61 64 73 74 72 00 73 65 74 70 72 69 6f 00 |.padstr.setprio.| +00008e00 63 76 74 6f 63 74 00 63 77 72 69 74 65 63 68 00 |cvtoct.cwritech.| +00008e10 67 65 74 74 69 6d 65 00 63 76 74 64 65 63 00 73 |gettime.cvtdec.s| +00008e20 74 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 6b 65 |trlen.bogus.fake| +00008e30 5f 65 78 69 74 00 00 2e 73 79 6d 74 61 62 00 2e |_exit...symtab..| +00008e40 73 74 72 74 61 62 00 2e 73 68 73 74 72 74 61 62 |strtab..shstrtab| +00008e50 00 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 00 2e |..text..rodata..| +00008e60 64 61 74 61 00 2e 62 73 73 00 00 00 00 00 00 00 |data..bss.......| +00008e70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00008e90 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +00008ea0 00 10 00 00 74 00 00 00 07 0a 00 00 00 00 00 00 |....t...........| +00008eb0 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +00008ec0 01 00 00 00 02 00 00 00 08 1a 00 00 7c 0a 00 00 |............|...| +00008ed0 b8 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +00008ee0 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +00008ef0 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +00008f00 00 00 00 00 01 00 00 00 00 00 00 00 2f 00 00 00 |............/...| +00008f10 08 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +00008f20 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +00008f30 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +00008f40 00 00 00 00 74 10 00 00 60 03 00 00 06 00 00 00 |....t...`.......| +00008f50 12 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +00008f60 03 00 00 00 00 00 00 00 00 00 00 00 d4 13 00 00 |................| +00008f70 62 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |b...............| +00008f80 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +00008f90 00 00 00 00 36 15 00 00 34 00 00 00 00 00 00 00 |....6...4.......| +00008fa0 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +00008fb0 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +00008fc0 02 00 03 00 01 00 00 00 b0 13 00 00 34 00 00 00 |............4...| +00008fd0 6c 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |l.......4. ...(.| +00008fe0 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +00008ff0 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +00009000 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +00009010 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +00009020 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +00009030 e5 53 51 81 ec b0 00 00 00 89 cb c7 45 f4 00 00 |.SQ.........E...| +00009040 00 00 c7 45 f0 05 00 00 00 c6 45 ef 68 8b 03 83 |...E......E.h...| +00009050 f8 02 74 1e 83 f8 03 75 2c 8b 43 04 83 c0 08 8b |..t....u,.C.....| +00009060 00 83 ec 08 6a 0a 50 e8 ed 05 00 00 83 c4 10 89 |....j.P.........| +00009070 45 f0 8b 43 04 83 c0 04 8b 00 0f b6 00 88 45 ef |E..C..........E.| +00009080 e9 a4 00 00 00 83 ec 04 ff 33 68 04 1a 00 00 8d |.........3h.....| +00009090 85 60 ff ff ff 50 e8 49 03 00 00 83 c4 10 83 ec |.`...P.I........| +000090a0 0c 8d 85 60 ff ff ff 50 e8 00 02 00 00 83 c4 10 |...`...P........| +000090b0 c7 45 e8 00 00 00 00 eb 59 8b 03 8d 14 85 00 00 |.E......Y.......| +000090c0 00 00 8b 43 04 01 d0 8b 00 85 c0 74 12 8b 03 8d |...C.......t....| +000090d0 14 85 00 00 00 00 8b 43 04 01 d0 8b 00 eb 05 b8 |.......C........| +000090e0 1b 1a 00 00 83 ec 04 50 68 22 1a 00 00 8d 85 60 |.......Ph".....`| +000090f0 ff ff ff 50 e8 eb 02 00 00 83 c4 10 83 ec 0c 8d |...P............| +00009100 85 60 ff ff ff 50 e8 a2 01 00 00 83 c4 10 83 45 |.`...P.........E| +00009110 e8 01 8b 45 e8 3b 03 7e a0 83 ec 0c 68 26 1a 00 |...E.;.~....h&..| +00009120 00 e8 87 01 00 00 83 c4 10 0f be 45 ef 83 ec 0c |...........E....| +00009130 50 e8 bf 01 00 00 83 c4 10 c7 85 50 ff ff ff 28 |P..........P...(| +00009140 1a 00 00 c7 85 54 ff ff ff 2e 1a 00 00 c7 85 58 |.....T.........X| +00009150 ff ff ff 30 1a 00 00 c7 85 5c ff ff ff 00 00 00 |...0.....\......| +00009160 00 c7 45 e4 00 00 00 00 eb 53 83 ec 08 8d 85 50 |..E......S.....P| +00009170 ff ff ff 50 6a 13 e8 9c 00 00 00 83 c4 10 89 45 |...Pj..........E| +00009180 e0 83 7d e0 00 79 32 0f be 45 ef ff 75 e0 50 68 |..}..y2..E..u.Ph| +00009190 34 1a 00 00 8d 85 60 ff ff ff 50 e8 44 02 00 00 |4.....`...P.D...| +000091a0 83 c4 10 83 ec 0c 8d 85 60 ff ff ff 50 e8 fb 00 |........`...P...| +000091b0 00 00 83 c4 10 83 45 f4 01 83 45 e4 01 8b 45 e4 |......E...E...E.| +000091c0 3b 45 f0 7c a5 83 ec 0c 6a 00 e8 ef 01 00 00 83 |;E.|....j.......| +000091d0 c4 10 0f be 45 ef 83 ec 0c 50 e8 16 01 00 00 83 |....E....P......| +000091e0 c4 10 83 ec 0c ff 75 f4 e8 71 01 00 00 83 c4 10 |......u..q......| +000091f0 b8 2a 00 00 00 8d 65 f8 59 5b 5d 8d 61 fc c3 55 |.*....e.Y[].a..U| +00009200 89 e5 83 ec 08 83 ec 08 ff 75 08 6a 00 e8 54 01 |.........u.j..T.| +00009210 00 00 83 c4 10 c9 c3 55 89 e5 81 ec 18 01 00 00 |.......U........| +00009220 e8 49 01 00 00 89 45 f4 83 7d f4 00 74 05 8b 45 |.I....E..}..t..E| +00009230 f4 eb 57 e8 56 01 00 00 89 45 f4 83 ec 08 ff 75 |..W.V....E.....u| +00009240 0c ff 75 08 e8 2d 01 00 00 83 c4 10 ff 75 08 ff |..u..-.......u..| +00009250 75 f4 68 57 1a 00 00 8d 85 f4 fe ff ff 50 e8 81 |u.hW.........P..| +00009260 01 00 00 83 c4 10 83 ec 0c 8d 85 f4 fe ff ff 50 |...............P| +00009270 e8 38 00 00 00 83 c4 10 83 ec 0c 6a ff e8 dc 00 |.8.........j....| +00009280 00 00 83 c4 10 b8 00 00 00 00 c9 c3 55 89 e5 83 |............U...| +00009290 ec 18 8b 45 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 |...E..E....j..E.| +000092a0 50 6a 00 e8 de 00 00 00 83 c4 10 c9 c3 55 89 e5 |Pj...........U..| +000092b0 83 ec 18 83 ec 0c ff 75 08 e8 0d 04 00 00 83 c4 |.......u........| +000092c0 10 89 45 f4 8b 45 f4 83 ec 04 50 ff 75 08 6a 00 |..E..E....P.u.j.| +000092d0 e8 b1 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 |..........U.....| +000092e0 83 ec 04 ff 75 0c ff 75 08 6a 00 e8 96 00 00 00 |....u..u.j......| +000092f0 83 c4 10 c9 c3 55 89 e5 83 ec 18 8b 45 08 88 45 |.....U......E..E| +00009300 f4 83 ec 04 6a 01 8d 45 f4 50 6a 01 e8 75 00 00 |....j..E.Pj..u..| +00009310 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 ec 0c ff |......U.........| +00009320 75 08 e8 a4 03 00 00 83 c4 10 89 45 f4 8b 45 f4 |u..........E..E.| +00009330 83 ec 04 50 ff 75 08 6a 01 e8 48 00 00 00 83 c4 |...P.u.j..H.....| +00009340 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff 75 0c ff |...U.........u..| +00009350 75 08 6a 01 e8 2d 00 00 00 83 c4 10 c9 c3 b8 00 |u.j..-..........| +00009360 00 00 00 cd 80 c3 b8 01 00 00 00 cd 80 c3 b8 02 |................| +00009370 00 00 00 cd 80 c3 b8 03 00 00 00 cd 80 c3 b8 04 |................| +00009380 00 00 00 cd 80 c3 b8 05 00 00 00 cd 80 c3 b8 06 |................| +00009390 00 00 00 cd 80 c3 b8 07 00 00 00 cd 80 c3 b8 08 |................| +000093a0 00 00 00 cd 80 c3 b8 09 00 00 00 cd 80 c3 b8 0a |................| +000093b0 00 00 00 cd 80 c3 b8 0b 00 00 00 cd 80 c3 b8 0c |................| +000093c0 00 00 00 cd 80 c3 b8 ad 0b 00 00 cd 80 c3 50 e8 |..............P.| +000093d0 8a ff ff ff e8 4b fc ff ff 83 ec 0c 50 e8 7c ff |.....K......P.|.| +000093e0 ff ff eb fe 55 89 e5 83 ec 38 8d 45 0c 83 c0 04 |....U....8.E....| +000093f0 89 45 f4 e9 3f 02 00 00 80 7d f3 25 0f 85 26 02 |.E..?....}.%..&.| +00009400 00 00 c7 45 ec 00 00 00 00 c7 45 e4 20 00 00 00 |...E......E. ...| +00009410 c7 45 e8 00 00 00 00 8b 45 0c 8d 50 01 89 55 0c |.E......E..P..U.| +00009420 0f b6 00 88 45 f3 80 7d f3 2d 75 16 c7 45 ec 01 |....E..}.-u..E..| +00009430 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 |....E..P..U.....| +00009440 45 f3 80 7d f3 30 75 40 c7 45 e4 30 00 00 00 8b |E..}.0u@.E.0....| +00009450 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 eb 28 |E..P..U.....E..(| +00009460 8b 55 e8 89 d0 c1 e0 02 01 d0 01 c0 89 45 e8 0f |.U...........E..| +00009470 be 45 f3 83 e8 30 01 45 e8 8b 45 0c 8d 50 01 89 |.E...0.E..E..P..| +00009480 55 0c 0f b6 00 88 45 f3 80 7d f3 2f 7e 06 80 7d |U.....E..}./~..}| +00009490 f3 39 7e cc 0f be 45 f3 83 e8 63 83 f8 15 0f 87 |.9~...E...c.....| +000094a0 93 01 00 00 8b 04 85 74 1a 00 00 ff e0 8b 45 f4 |.......t......E.| +000094b0 8d 50 04 89 55 f4 8b 00 88 45 f3 0f b6 45 f3 88 |.P..U....E...E..| +000094c0 45 d0 c6 45 d1 00 83 ec 08 ff 75 e4 ff 75 ec ff |E..E......u..u..| +000094d0 75 e8 6a 01 8d 45 d0 50 ff 75 08 e8 89 04 00 00 |u.j..E.P.u......| +000094e0 83 c4 20 89 45 08 e9 4c 01 00 00 8b 45 f4 8d 50 |.. .E..L....E..P| +000094f0 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 ea |..U......P.E.P..| +00009500 01 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff |.......E.....u..| +00009510 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 |u..u..u..E.P.u..| +00009520 45 04 00 00 83 c4 20 89 45 08 e9 08 01 00 00 8b |E..... .E.......| +00009530 45 f4 8d 50 04 89 55 f4 8b 00 89 45 dc 83 ec 08 |E..P..U....E....| +00009540 ff 75 e4 ff 75 ec ff 75 e8 6a ff ff 75 dc ff 75 |.u..u..u.j..u..u| +00009550 08 e8 13 04 00 00 83 c4 20 89 45 08 e9 d6 00 00 |........ .E.....| +00009560 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 |..E..P..U......P| +00009570 8d 45 d0 50 e8 44 02 00 00 83 c4 10 89 45 e0 83 |.E.P.D.......E..| +00009580 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 |...u..u..u..u..E| +00009590 d0 50 ff 75 08 e8 cf 03 00 00 83 c4 20 89 45 08 |.P.u........ .E.| +000095a0 e9 92 00 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 |......E..P..U...| +000095b0 83 ec 08 50 8d 45 d0 50 e8 8a 02 00 00 83 c4 10 |...P.E.P........| +000095c0 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff |.E.....u..u..u..| +000095d0 75 e0 8d 45 d0 50 ff 75 08 e8 8b 03 00 00 83 c4 |u..E.P.u........| +000095e0 20 89 45 08 eb 51 8b 45 f4 8d 50 04 89 55 f4 8b | .E..Q.E..P..U..| +000095f0 00 83 ec 08 50 8d 45 d0 50 e8 d3 02 00 00 83 c4 |....P.E.P.......| +00009600 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 |..E.....u..u..u.| +00009610 ff 75 e0 8d 45 d0 50 ff 75 08 e8 4a 03 00 00 83 |.u..E.P.u..J....| +00009620 c4 20 89 45 08 90 eb 0f 8b 45 08 8d 50 01 89 55 |. .E.....E..P..U| +00009630 08 0f b6 55 f3 88 10 8b 45 0c 8d 50 01 89 55 0c |...U....E..P..U.| +00009640 0f b6 00 88 45 f3 80 7d f3 00 0f 85 a8 fd ff ff |....E..}........| +00009650 8b 45 08 c6 00 00 90 c9 c3 55 89 e5 53 83 ec 14 |.E.......U..S...| +00009660 8b 45 08 8b 4d 0c bb 00 00 00 00 c6 45 eb 39 c7 |.E..M.......E.9.| +00009670 45 f8 01 00 00 00 0f b6 10 80 fa 2d 75 0a c7 45 |E..........-u..E| +00009680 f8 ff ff ff ff 83 c0 01 83 f9 0a 74 2b 89 ca 83 |...........t+...| +00009690 c2 2f 88 55 eb eb 21 0f b6 10 80 fa 2f 7e 20 0f |./.U..!...../~ .| +000096a0 b6 10 38 55 eb 7c 18 0f af d9 0f b6 10 0f be d2 |..8U.|..........| +000096b0 01 da 8d 5a d0 83 c0 01 0f b6 10 84 d2 75 d8 89 |...Z.........u..| +000096c0 d8 0f af 45 f8 83 c4 14 5b 5d c3 55 89 e5 53 8b |...E....[].U..S.| +000096d0 55 08 bb 00 00 00 00 eb 03 83 c3 01 89 d0 8d 50 |U..............P| +000096e0 01 0f b6 00 84 c0 75 f1 89 d8 5b 5d c3 55 89 e5 |......u...[].U..| +000096f0 83 ec 18 8b 45 08 89 45 f4 83 7d 0c 00 79 0f 8b |....E..E..}..y..| +00009700 45 f4 8d 50 01 89 55 f4 c6 00 2d f7 5d 0c 83 ec |E..P..U...-.]...| +00009710 08 ff 75 0c ff 75 f4 e8 18 00 00 00 83 c4 10 89 |..u..u..........| +00009720 45 f4 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 |E..E.....U..E.).| +00009730 89 d0 c9 c3 55 89 e5 83 ec 18 8b 4d 0c ba 67 66 |....U......M..gf| +00009740 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 |ff............).| +00009750 89 d0 89 45 f4 83 7d f4 00 79 0e c7 45 f4 cc cc |...E..}..y..E...| +00009760 cc 0c c7 45 0c 08 00 00 00 83 7d f4 00 74 14 83 |...E......}..t..| +00009770 ec 08 ff 75 f4 ff 75 08 e8 b7 ff ff ff 83 c4 10 |...u..u.........| +00009780 89 45 08 8b 4d 0c ba 67 66 66 66 89 c8 f7 ea c1 |.E..M..gfff.....| +00009790 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 c1 e0 02 01 d0 |.......)........| +000097a0 01 c0 29 c1 89 ca 89 d0 8d 48 30 8b 45 08 8d 50 |..)......H0.E..P| +000097b0 01 89 55 08 89 ca 88 10 8b 45 08 c9 c3 55 89 e5 |..U......E...U..| +000097c0 83 ec 20 c7 45 e3 30 31 32 33 c7 45 e7 34 35 36 |.. .E.0123.E.456| +000097d0 37 c7 45 eb 38 39 41 42 c7 45 ef 43 44 45 46 c6 |7.E.89AB.E.CDEF.| +000097e0 45 f3 00 c7 45 fc 00 00 00 00 c7 45 f8 00 00 00 |E...E......E....| +000097f0 00 eb 43 8b 45 0c 25 00 00 00 f0 89 45 f4 83 7d |..C.E.%.....E..}| +00009800 fc 00 75 0c 83 7d f4 00 75 06 83 7d f8 07 75 1e |..u..}..u..}..u.| +00009810 83 45 fc 01 c1 6d f4 1c 8b 45 08 8d 50 01 89 55 |.E...m...E..P..U| +00009820 08 8d 4d e3 8b 55 f4 01 ca 0f b6 12 88 10 c1 65 |..M..U.........e| +00009830 0c 04 83 45 f8 01 83 7d f8 07 7e b7 8b 45 08 c6 |...E...}..~..E..| +00009840 00 00 8b 45 fc c9 c3 55 89 e5 83 ec 10 c7 45 f8 |...E...U......E.| +00009850 00 00 00 00 8b 45 08 89 45 f4 8b 45 0c 25 00 00 |.....E..E..E.%..| +00009860 00 c0 89 45 f0 c1 6d f0 1e c7 45 fc 00 00 00 00 |...E..m...E.....| +00009870 eb 47 83 7d fc 0a 74 0c 83 7d f0 00 75 06 83 7d |.G.}..t..}..u..}| +00009880 f8 00 74 1e c7 45 f8 01 00 00 00 83 65 f0 07 8b |..t..E......e...| +00009890 45 f0 8d 48 30 8b 45 f4 8d 50 01 89 55 f4 89 ca |E..H0.E..P..U...| +000098a0 88 10 c1 65 0c 03 8b 45 0c 25 00 00 00 e0 89 45 |...e...E.%.....E| +000098b0 f0 c1 6d f0 1d 83 45 fc 01 83 7d fc 0a 7e b3 8b |..m...E...}..~..| +000098c0 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 |E.....U..E.)....| +000098d0 c3 55 89 e5 83 ec 18 8b 45 08 89 45 f4 83 ec 08 |.U......E..E....| +000098e0 ff 75 0c ff 75 f4 e8 18 00 00 00 83 c4 10 89 45 |.u..u..........E| +000098f0 f4 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 |..E.....U..E.)..| +00009900 d0 c9 c3 55 89 e5 83 ec 18 8b 45 0c ba cd cc cc |...U......E.....| +00009910 cc f7 e2 89 d0 c1 e8 03 89 45 f4 83 7d f4 00 74 |.........E..}..t| +00009920 15 8b 45 f4 83 ec 08 50 ff 75 08 e8 04 fe ff ff |..E....P.u......| +00009930 83 c4 10 89 45 08 8b 4d 0c ba cd cc cc cc 89 c8 |....E..M........| +00009940 f7 e2 c1 ea 03 89 d0 c1 e0 02 01 d0 01 c0 29 c1 |..............).| +00009950 89 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 |.....H0.E..P..U.| +00009960 89 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 ec 18 83 |.....E...U......| +00009970 7d 10 00 79 11 83 ec 0c ff 75 0c e8 4b fd ff ff |}..y.....u..K...| +00009980 83 c4 10 89 45 10 8b 45 14 2b 45 10 89 45 f0 83 |....E..E.+E..E..| +00009990 7d f0 00 7e 1d 83 7d 18 00 75 17 83 ec 04 ff 75 |}..~..}..u.....u| +000099a0 1c ff 75 f0 ff 75 08 e8 5a 00 00 00 83 c4 10 89 |..u..u..Z.......| +000099b0 45 08 c7 45 f4 00 00 00 00 eb 1b 8b 55 f4 8b 45 |E..E........U..E| +000099c0 0c 8d 0c 02 8b 45 08 8d 50 01 89 55 08 0f b6 11 |.....E..P..U....| +000099d0 88 10 83 45 f4 01 8b 45 f4 3b 45 10 7c dd 83 7d |...E...E.;E.|..}| +000099e0 f0 00 7e 1d 83 7d 18 00 74 17 83 ec 04 ff 75 1c |..~..}..t.....u.| +000099f0 ff 75 f0 ff 75 08 e8 0b 00 00 00 83 c4 10 89 45 |.u..u..........E| +00009a00 08 8b 45 08 c9 c3 55 89 e5 eb 12 8b 45 08 8d 50 |..E...U.....E..P| +00009a10 01 89 55 08 8b 55 10 88 10 83 6d 0c 01 83 7d 0c |..U..U....m...}.| +00009a20 00 7f e8 8b 45 08 5d c3 75 73 65 72 48 3a 20 61 |....E.].userH: a| +00009a30 72 67 63 20 25 64 2c 20 61 72 67 73 3a 20 00 28 |rgc %d, args: .(| +00009a40 6e 75 6c 6c 29 00 20 25 73 00 0a 00 75 73 65 72 |null). %s...user| +00009a50 5a 00 5a 00 31 30 00 00 21 21 20 25 63 20 73 70 |Z.Z.10..!! %c sp| +00009a60 61 77 6e 28 29 20 66 61 69 6c 65 64 2c 20 72 65 |awn() failed, re| +00009a70 74 75 72 6e 65 64 20 25 64 0a 00 43 68 69 6c 64 |turned %d..Child| +00009a80 20 25 64 20 65 78 65 63 28 29 20 23 25 75 20 66 | %d exec() #%u f| +00009a90 61 69 6c 65 64 0a 00 00 89 14 00 00 c7 14 00 00 |ailed...........| +00009aa0 13 16 00 00 13 16 00 00 13 16 00 00 13 16 00 00 |................| +* +00009ac0 13 16 00 00 13 16 00 00 81 15 00 00 13 16 00 00 |................| +00009ad0 13 16 00 00 13 16 00 00 0b 15 00 00 13 16 00 00 |................| +00009ae0 c2 15 00 00 13 16 00 00 13 16 00 00 3d 15 00 00 |............=...| +00009af0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +0000a030 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +0000a040 03 00 01 00 00 00 00 00 04 1a 00 00 00 00 00 00 |................| +0000a050 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +0000a060 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +0000a070 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +0000a080 04 00 f1 ff 09 00 00 00 00 00 00 00 00 00 00 00 |................| +0000a090 04 00 f1 ff 11 00 00 00 00 00 00 00 00 00 00 00 |................| +0000a0a0 04 00 f1 ff 1a 00 00 00 00 00 00 00 00 00 00 00 |................| +0000a0b0 04 00 f1 ff 24 00 00 00 00 00 00 00 00 00 00 00 |....$...........| +0000a0c0 04 00 f1 ff 2d 00 00 00 00 00 00 00 00 00 00 00 |....-...........| +0000a0d0 04 00 f1 ff 36 00 00 00 00 00 00 00 00 00 00 00 |....6...........| +0000a0e0 04 00 f1 ff 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +0000a0f0 04 00 f1 ff 49 00 00 00 00 00 00 00 00 00 00 00 |....I...........| +0000a100 04 00 f1 ff 52 00 00 00 00 00 00 00 00 00 00 00 |....R...........| +0000a110 04 00 f1 ff 5b 00 00 00 00 00 00 00 00 00 00 00 |....[...........| +0000a120 04 00 f1 ff 65 00 00 00 00 00 00 00 00 00 00 00 |....e...........| +0000a130 04 00 f1 ff 6e 00 00 00 00 00 00 00 00 00 00 00 |....n...........| +0000a140 04 00 f1 ff 74 00 00 00 d1 12 00 00 21 00 00 00 |....t.......!...| +0000a150 12 00 01 00 7d 00 00 00 42 13 00 00 00 00 00 00 |....}...B.......| +0000a160 10 00 01 00 85 00 00 00 b6 12 00 00 1b 00 00 00 |................| +0000a170 12 00 01 00 8c 00 00 00 35 16 00 00 72 00 00 00 |........5...r...| +0000a180 12 00 01 00 94 00 00 00 ad 18 00 00 32 00 00 00 |............2...| +0000a190 12 00 01 00 9b 00 00 00 6a 13 00 00 00 00 00 00 |........j.......| +0000a1a0 10 00 01 00 a2 00 00 00 9a 13 00 00 00 00 00 00 |................| +0000a1b0 10 00 01 00 a8 00 00 00 1f 13 00 00 1b 00 00 00 |................| +0000a1c0 12 00 01 00 af 00 00 00 e2 19 00 00 22 00 00 00 |............"...| +0000a1d0 12 00 01 00 b3 00 00 00 f3 11 00 00 75 00 00 00 |............u...| +0000a1e0 12 00 01 00 b9 00 00 00 c0 13 00 00 75 02 00 00 |............u...| +0000a1f0 12 00 01 00 c0 00 00 00 99 17 00 00 8a 00 00 00 |................| +0000a200 12 00 01 00 c7 00 00 00 df 18 00 00 66 00 00 00 |............f...| +0000a210 12 00 01 00 86 00 00 00 62 13 00 00 00 00 00 00 |........b.......| +0000a220 10 00 01 00 cf 00 00 00 92 13 00 00 00 00 00 00 |................| +0000a230 10 00 01 00 d4 00 00 00 89 12 00 00 2d 00 00 00 |............-...| +0000a240 12 00 01 00 dc 00 00 00 52 13 00 00 00 00 00 00 |........R.......| +0000a250 10 00 01 00 e1 00 00 00 db 11 00 00 18 00 00 00 |................| +0000a260 12 00 01 00 e6 00 00 00 f2 12 00 00 2d 00 00 00 |............-...| +0000a270 12 00 01 00 ee 00 00 00 b0 13 00 00 00 00 00 00 |................| +0000a280 10 00 01 00 f5 00 00 00 5a 13 00 00 00 00 00 00 |........Z.......| +0000a290 10 00 01 00 fa 00 00 00 82 13 00 00 00 00 00 00 |................| +0000a2a0 10 00 01 00 02 01 00 00 10 17 00 00 89 00 00 00 |................| +0000a2b0 12 00 01 00 0a 01 00 00 4a 13 00 00 00 00 00 00 |........J.......| +0000a2c0 10 00 01 00 0f 01 00 00 00 10 00 00 db 01 00 00 |................| +0000a2d0 12 00 01 00 14 01 00 00 72 13 00 00 00 00 00 00 |........r.......| +0000a2e0 10 00 01 00 1c 01 00 00 45 19 00 00 9d 00 00 00 |........E.......| +0000a2f0 12 00 01 00 23 01 00 00 8a 13 00 00 00 00 00 00 |....#...........| +0000a300 10 00 01 00 2b 01 00 00 23 18 00 00 8a 00 00 00 |....+...#.......| +0000a310 12 00 01 00 32 01 00 00 68 12 00 00 21 00 00 00 |....2...h...!...| +0000a320 12 00 01 00 3b 01 00 00 7a 13 00 00 00 00 00 00 |....;...z.......| +0000a330 10 00 01 00 43 01 00 00 c9 16 00 00 47 00 00 00 |....C.......G...| +0000a340 12 00 01 00 5c 01 00 00 3a 13 00 00 00 00 00 00 |....\...:.......| +0000a350 10 00 01 00 4a 01 00 00 a7 16 00 00 22 00 00 00 |....J......."...| +0000a360 12 00 01 00 51 01 00 00 a2 13 00 00 00 00 00 00 |....Q...........| +0000a370 10 00 01 00 57 01 00 00 aa 13 00 00 00 00 00 00 |....W...........| +0000a380 10 00 01 00 00 70 72 6f 67 48 2e 63 00 75 6c 69 |.....progH.c.uli| +0000a390 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 74 |bc.c.sprint.c.st| +0000a3a0 72 32 69 6e 74 2e 63 00 73 74 72 6c 65 6e 2e 63 |r2int.c.strlen.c| +0000a3b0 00 63 76 74 64 65 63 2e 63 00 63 76 74 64 65 63 |.cvtdec.c.cvtdec| +0000a3c0 30 2e 63 00 63 76 74 68 65 78 2e 63 00 63 76 74 |0.c.cvthex.c.cvt| +0000a3d0 6f 63 74 2e 63 00 63 76 74 75 6e 73 2e 63 00 63 |oct.c.cvtuns.c.c| +0000a3e0 76 74 75 6e 73 30 2e 63 00 70 61 64 73 74 72 2e |vtuns0.c.padstr.| +0000a3f0 63 00 70 61 64 2e 63 00 73 77 72 69 74 65 63 68 |c.pad.c.swritech| +0000a400 00 77 61 69 74 70 69 64 00 63 77 72 69 74 65 00 |.waitpid.cwrite.| +0000a410 73 74 72 32 69 6e 74 00 63 76 74 75 6e 73 00 67 |str2int.cvtuns.g| +0000a420 65 74 70 69 64 00 73 6c 65 65 70 00 73 77 72 69 |etpid.sleep.swri| +0000a430 74 65 00 70 61 64 00 73 70 61 77 6e 00 73 70 72 |te.pad.spawn.spr| +0000a440 69 6e 74 00 63 76 74 68 65 78 00 63 76 74 75 6e |int.cvthex.cvtun| +0000a450 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 65 73 00 |s0.kill.cwrites.| +0000a460 65 78 65 63 00 77 61 69 74 00 73 77 72 69 74 65 |exec.wait.swrite| +0000a470 73 00 5f 73 74 61 72 74 00 72 65 61 64 00 67 65 |s._start.read.ge| +0000a480 74 70 72 69 6f 00 63 76 74 64 65 63 30 00 66 6f |tprio.cvtdec0.fo| +0000a490 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 69 64 00 |rk.main.getppid.| +0000a4a0 70 61 64 73 74 72 00 73 65 74 70 72 69 6f 00 63 |padstr.setprio.c| +0000a4b0 76 74 6f 63 74 00 63 77 72 69 74 65 63 68 00 67 |vtoct.cwritech.g| +0000a4c0 65 74 74 69 6d 65 00 63 76 74 64 65 63 00 73 74 |ettime.cvtdec.st| +0000a4d0 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 6b 65 5f |rlen.bogus.fake_| +0000a4e0 65 78 69 74 00 00 2e 73 79 6d 74 61 62 00 2e 73 |exit...symtab..s| +0000a4f0 74 72 74 61 62 00 2e 73 68 73 74 72 74 61 62 00 |trtab..shstrtab.| +0000a500 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 00 2e 64 |.text..rodata..d| +0000a510 61 74 61 00 2e 62 73 73 00 00 00 00 00 00 00 00 |ata..bss........| +0000a520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +0000a540 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +0000a550 00 10 00 00 74 00 00 00 04 0a 00 00 00 00 00 00 |....t...........| +0000a560 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +0000a570 01 00 00 00 02 00 00 00 04 1a 00 00 78 0a 00 00 |............x...| +0000a580 c8 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +0000a590 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +0000a5a0 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +0000a5b0 00 00 00 00 01 00 00 00 00 00 00 00 2f 00 00 00 |............/...| +0000a5c0 08 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +0000a5d0 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +0000a5e0 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +0000a5f0 00 00 00 00 74 10 00 00 60 03 00 00 06 00 00 00 |....t...`.......| +0000a600 12 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +0000a610 03 00 00 00 00 00 00 00 00 00 00 00 d4 13 00 00 |................| +0000a620 61 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |a...............| +0000a630 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +0000a640 00 00 00 00 35 15 00 00 34 00 00 00 00 00 00 00 |....5...4.......| +0000a650 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +0000a660 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +0000a670 02 00 03 00 01 00 00 00 3d 15 00 00 34 00 00 00 |........=...4...| +0000a680 6c 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |l.......4. ...(.| +0000a690 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +0000a6a0 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +0000a6b0 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +0000a6c0 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +0000a6d0 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +0000a6e0 e5 53 51 81 ec 90 01 00 00 89 cb c7 45 f4 05 00 |.SQ.........E...| +0000a6f0 00 00 c6 45 d3 69 c7 45 e0 05 00 00 00 c7 85 4f |...E.i.E.......O| +0000a700 ff ff ff 2a 3f 2a 00 c7 45 f0 00 00 00 00 8b 03 |...*?*..E.......| +0000a710 83 f8 02 74 29 83 f8 03 74 0b 83 f8 01 0f 84 d4 |...t)...t.......| +0000a720 00 00 00 eb 2c 8b 43 04 83 c0 08 8b 00 83 ec 08 |....,.C.........| +0000a730 6a 0a 50 e8 5e 07 00 00 83 c4 10 89 45 f4 8b 43 |j.P.^.......E..C| +0000a740 04 83 c0 04 8b 00 0f b6 00 88 45 d3 e9 a7 00 00 |..........E.....| +0000a750 00 83 ec 04 ff 33 68 94 1b 00 00 8d 85 53 ff ff |.....3h......S..| +0000a760 ff 50 e8 ba 04 00 00 83 c4 10 83 ec 0c 8d 85 53 |.P.............S| +0000a770 ff ff ff 50 e8 71 03 00 00 83 c4 10 c7 45 ec 00 |...P.q.......E..| +0000a780 00 00 00 eb 59 8b 03 8d 14 85 00 00 00 00 8b 43 |....Y..........C| +0000a790 04 01 d0 8b 00 85 c0 74 12 8b 03 8d 14 85 00 00 |.......t........| +0000a7a0 00 00 8b 43 04 01 d0 8b 00 eb 05 b8 ab 1b 00 00 |...C............| +0000a7b0 83 ec 04 50 68 b2 1b 00 00 8d 85 53 ff ff ff 50 |...Ph......S...P| +0000a7c0 e8 5c 04 00 00 83 c4 10 83 ec 0c 8d 85 53 ff ff |.\...........S..| +0000a7d0 ff 50 e8 13 03 00 00 83 c4 10 83 45 ec 01 8b 45 |.P.........E...E| +0000a7e0 ec 3b 03 7e a0 83 ec 0c 68 b6 1b 00 00 e8 f8 02 |.;.~....h.......| +0000a7f0 00 00 83 c4 10 eb 01 90 0f b6 45 d3 88 85 50 ff |..........E...P.| +0000a800 ff ff 83 ec 04 6a 01 8d 45 d3 50 6a 01 e8 b1 03 |.....j..E.Pj....| +0000a810 00 00 83 c4 10 c7 85 70 fe ff ff b8 1b 00 00 c7 |.......p........| +0000a820 85 74 fe ff ff be 1b 00 00 c7 85 78 fe ff ff c0 |.t.........x....| +0000a830 1b 00 00 c7 85 7c fe ff ff c3 1b 00 00 c7 85 80 |.....|..........| +0000a840 fe ff ff 00 00 00 00 c7 45 e8 00 00 00 00 eb 5b |........E......[| +0000a850 83 ec 08 8d 85 70 fe ff ff 50 6a 10 e8 f3 01 00 |.....p...Pj.....| +0000a860 00 83 c4 10 89 45 d4 83 7d d4 00 79 14 83 ec 0c |.....E..}..y....| +0000a870 8d 85 4f ff ff ff 50 e8 d7 02 00 00 83 c4 10 eb |..O...P.........| +0000a880 26 0f b6 45 d3 0f be c0 83 ec 0c 50 e8 a1 02 00 |&..E.......P....| +0000a890 00 83 c4 10 8b 45 f0 8d 50 01 89 55 f0 8b 55 d4 |.....E..P..U..U.| +0000a8a0 89 94 85 84 fe ff ff 83 45 e8 01 8b 45 e8 3b 45 |........E...E.;E| +0000a8b0 f4 7c 9d 8b 45 e0 69 c0 e8 03 00 00 83 ec 0c 50 |.|..E.i........P| +0000a8c0 e8 36 03 00 00 83 c4 10 8b 85 88 fe ff ff 83 ec |.6..............| +0000a8d0 0c 50 e8 1c 03 00 00 83 c4 10 89 45 dc 83 7d dc |.P.........E..}.| +0000a8e0 00 74 45 8b 95 88 fe ff ff 0f b6 45 d3 0f be c0 |.tE........E....| +0000a8f0 83 ec 0c ff 75 dc 52 50 68 c5 1b 00 00 8d 85 53 |....u.RPh......S| +0000a900 ff ff ff 50 e8 18 03 00 00 83 c4 20 83 ec 0c 8d |...P....... ....| +0000a910 85 53 ff ff ff 50 e8 cf 01 00 00 83 c4 10 c7 85 |.S...P..........| +0000a920 88 fe ff ff d6 ff ff ff 8b 85 90 fe ff ff 83 ec |................| +0000a930 0c 50 e8 bc 02 00 00 83 c4 10 89 45 dc 83 7d dc |.P.........E..}.| +0000a940 00 74 45 8b 95 90 fe ff ff 0f b6 45 d3 0f be c0 |.tE........E....| +0000a950 83 ec 0c ff 75 dc 52 50 68 c5 1b 00 00 8d 85 53 |....u.RPh......S| +0000a960 ff ff ff 50 e8 b8 02 00 00 83 c4 20 83 ec 0c 8d |...P....... ....| +0000a970 85 53 ff ff ff 50 e8 6f 01 00 00 83 c4 10 c7 85 |.S...P.o........| +0000a980 90 fe ff ff d6 ff ff ff 83 ec 08 6a 00 6a 00 e8 |...........j.j..| +0000a990 0f 02 00 00 83 c4 10 89 45 d8 83 7d d8 fc 74 7f |........E..}..t.| +0000a9a0 c7 45 e4 00 00 00 00 eb 54 8b 45 e4 8b 94 85 84 |.E......T.E.....| +0000a9b0 fe ff ff 8b 45 d8 39 c2 75 3f 8b 45 e4 8b 94 85 |....E.9.u?.E....| +0000a9c0 84 fe ff ff 0f b6 45 d3 0f be c0 83 ec 0c 52 ff |......E.......R.| +0000a9d0 75 e4 50 68 e0 1b 00 00 8d 85 53 ff ff ff 50 e8 |u.Ph......S...P.| +0000a9e0 3d 02 00 00 83 c4 20 83 ec 0c 8d 85 53 ff ff ff |=..... .....S...| +0000a9f0 50 e8 f4 00 00 00 83 c4 10 83 45 e4 01 8b 45 e4 |P.........E...E.| +0000aa00 3b 45 f4 7c a4 8b 45 e0 69 c0 e8 03 00 00 83 ec |;E.|..E.i.......| +0000aa10 0c 50 e8 e4 01 00 00 83 c4 10 e9 69 ff ff ff 90 |.P.........i....| +0000aa20 83 ec 0c 6a 00 e8 71 01 00 00 83 c4 10 b8 2a 00 |...j..q.......*.| +0000aa30 00 00 8d 65 f8 59 5b 5d 8d 61 fc c3 55 89 e5 83 |...e.Y[].a..U...| +0000aa40 ec 08 83 ec 08 ff 75 08 6a 00 e8 54 01 00 00 83 |......u.j..T....| +0000aa50 c4 10 c9 c3 55 89 e5 81 ec 18 01 00 00 e8 49 01 |....U.........I.| +0000aa60 00 00 89 45 f4 83 7d f4 00 74 05 8b 45 f4 eb 57 |...E..}..t..E..W| +0000aa70 e8 56 01 00 00 89 45 f4 83 ec 08 ff 75 0c ff 75 |.V....E.....u..u| +0000aa80 08 e8 2d 01 00 00 83 c4 10 ff 75 08 ff 75 f4 68 |..-.......u..u.h| +0000aa90 f6 1b 00 00 8d 85 f4 fe ff ff 50 e8 81 01 00 00 |..........P.....| +0000aaa0 83 c4 10 83 ec 0c 8d 85 f4 fe ff ff 50 e8 38 00 |............P.8.| +0000aab0 00 00 83 c4 10 83 ec 0c 6a ff e8 dc 00 00 00 83 |........j.......| +0000aac0 c4 10 b8 00 00 00 00 c9 c3 55 89 e5 83 ec 18 8b |.........U......| +0000aad0 45 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 00 |E..E....j..E.Pj.| +0000aae0 e8 de 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 |..........U.....| +0000aaf0 83 ec 0c ff 75 08 e8 0d 04 00 00 83 c4 10 89 45 |....u..........E| +0000ab00 f4 8b 45 f4 83 ec 04 50 ff 75 08 6a 00 e8 b1 00 |..E....P.u.j....| +0000ab10 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 |.......U........| +0000ab20 ff 75 0c ff 75 08 6a 00 e8 96 00 00 00 83 c4 10 |.u..u.j.........| +0000ab30 c9 c3 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec |..U......E..E...| +0000ab40 04 6a 01 8d 45 f4 50 6a 01 e8 75 00 00 00 83 c4 |.j..E.Pj..u.....| +0000ab50 10 c9 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 |...U.........u..| +0000ab60 a4 03 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 |........E..E....| +0000ab70 50 ff 75 08 6a 01 e8 48 00 00 00 83 c4 10 c9 c3 |P.u.j..H........| +0000ab80 55 89 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a |U.........u..u.j| +0000ab90 01 e8 2d 00 00 00 83 c4 10 c9 c3 b8 00 00 00 00 |..-.............| +0000aba0 cd 80 c3 b8 01 00 00 00 cd 80 c3 b8 02 00 00 00 |................| +0000abb0 cd 80 c3 b8 03 00 00 00 cd 80 c3 b8 04 00 00 00 |................| +0000abc0 cd 80 c3 b8 05 00 00 00 cd 80 c3 b8 06 00 00 00 |................| +0000abd0 cd 80 c3 b8 07 00 00 00 cd 80 c3 b8 08 00 00 00 |................| +0000abe0 cd 80 c3 b8 09 00 00 00 cd 80 c3 b8 0a 00 00 00 |................| +0000abf0 cd 80 c3 b8 0b 00 00 00 cd 80 c3 b8 0c 00 00 00 |................| +0000ac00 cd 80 c3 b8 ad 0b 00 00 cd 80 c3 50 e8 8a ff ff |...........P....| +0000ac10 ff e8 be fa ff ff 83 ec 0c 50 e8 7c ff ff ff eb |.........P.|....| +0000ac20 fe 55 89 e5 83 ec 38 8d 45 0c 83 c0 04 89 45 f4 |.U....8.E.....E.| +0000ac30 e9 3f 02 00 00 80 7d f3 25 0f 85 26 02 00 00 c7 |.?....}.%..&....| +0000ac40 45 ec 00 00 00 00 c7 45 e4 20 00 00 00 c7 45 e8 |E......E. ....E.| +0000ac50 00 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |.....E..P..U....| +0000ac60 88 45 f3 80 7d f3 2d 75 16 c7 45 ec 01 00 00 00 |.E..}.-u..E.....| +0000ac70 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 |.E..P..U.....E..| +0000ac80 7d f3 30 75 40 c7 45 e4 30 00 00 00 8b 45 0c 8d |}.0u@.E.0....E..| +0000ac90 50 01 89 55 0c 0f b6 00 88 45 f3 eb 28 8b 55 e8 |P..U.....E..(.U.| +0000aca0 89 d0 c1 e0 02 01 d0 01 c0 89 45 e8 0f be 45 f3 |..........E...E.| +0000acb0 83 e8 30 01 45 e8 8b 45 0c 8d 50 01 89 55 0c 0f |..0.E..E..P..U..| +0000acc0 b6 00 88 45 f3 80 7d f3 2f 7e 06 80 7d f3 39 7e |...E..}./~..}.9~| +0000acd0 cc 0f be 45 f3 83 e8 63 83 f8 15 0f 87 93 01 00 |...E...c........| +0000ace0 00 8b 04 85 14 1c 00 00 ff e0 8b 45 f4 8d 50 04 |...........E..P.| +0000acf0 89 55 f4 8b 00 88 45 f3 0f b6 45 f3 88 45 d0 c6 |.U....E...E..E..| +0000ad00 45 d1 00 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a |E......u..u..u.j| +0000ad10 01 8d 45 d0 50 ff 75 08 e8 89 04 00 00 83 c4 20 |..E.P.u........ | +0000ad20 89 45 08 e9 4c 01 00 00 8b 45 f4 8d 50 04 89 55 |.E..L....E..P..U| +0000ad30 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 ea 01 00 00 |......P.E.P.....| +0000ad40 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff |....E.....u..u..| +0000ad50 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 45 04 00 |u..u..E.P.u..E..| +0000ad60 00 83 c4 20 89 45 08 e9 08 01 00 00 8b 45 f4 8d |... .E.......E..| +0000ad70 50 04 89 55 f4 8b 00 89 45 dc 83 ec 08 ff 75 e4 |P..U....E.....u.| +0000ad80 ff 75 ec ff 75 e8 6a ff ff 75 dc ff 75 08 e8 13 |.u..u.j..u..u...| +0000ad90 04 00 00 83 c4 20 89 45 08 e9 d6 00 00 00 8b 45 |..... .E.......E| +0000ada0 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 |..P..U......P.E.| +0000adb0 50 e8 44 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff |P.D.......E.....| +0000adc0 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff |u..u..u..u..E.P.| +0000add0 75 08 e8 cf 03 00 00 83 c4 20 89 45 08 e9 92 00 |u........ .E....| +0000ade0 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 |...E..P..U......| +0000adf0 50 8d 45 d0 50 e8 8a 02 00 00 83 c4 10 89 45 e0 |P.E.P.........E.| +0000ae00 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d |....u..u..u..u..| +0000ae10 45 d0 50 ff 75 08 e8 8b 03 00 00 83 c4 20 89 45 |E.P.u........ .E| +0000ae20 08 eb 51 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec |..Q.E..P..U.....| +0000ae30 08 50 8d 45 d0 50 e8 d3 02 00 00 83 c4 10 89 45 |.P.E.P.........E| +0000ae40 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 |.....u..u..u..u.| +0000ae50 8d 45 d0 50 ff 75 08 e8 4a 03 00 00 83 c4 20 89 |.E.P.u..J..... .| +0000ae60 45 08 90 eb 0f 8b 45 08 8d 50 01 89 55 08 0f b6 |E.....E..P..U...| +0000ae70 55 f3 88 10 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |U....E..P..U....| +0000ae80 88 45 f3 80 7d f3 00 0f 85 a8 fd ff ff 8b 45 08 |.E..}.........E.| +0000ae90 c6 00 00 90 c9 c3 55 89 e5 53 83 ec 14 8b 45 08 |......U..S....E.| +0000aea0 8b 4d 0c bb 00 00 00 00 c6 45 eb 39 c7 45 f8 01 |.M.......E.9.E..| +0000aeb0 00 00 00 0f b6 10 80 fa 2d 75 0a c7 45 f8 ff ff |........-u..E...| +0000aec0 ff ff 83 c0 01 83 f9 0a 74 2b 89 ca 83 c2 2f 88 |........t+..../.| +0000aed0 55 eb eb 21 0f b6 10 80 fa 2f 7e 20 0f b6 10 38 |U..!...../~ ...8| +0000aee0 55 eb 7c 18 0f af d9 0f b6 10 0f be d2 01 da 8d |U.|.............| +0000aef0 5a d0 83 c0 01 0f b6 10 84 d2 75 d8 89 d8 0f af |Z.........u.....| +0000af00 45 f8 83 c4 14 5b 5d c3 55 89 e5 53 8b 55 08 bb |E....[].U..S.U..| +0000af10 00 00 00 00 eb 03 83 c3 01 89 d0 8d 50 01 0f b6 |............P...| +0000af20 00 84 c0 75 f1 89 d8 5b 5d c3 55 89 e5 83 ec 18 |...u...[].U.....| +0000af30 8b 45 08 89 45 f4 83 7d 0c 00 79 0f 8b 45 f4 8d |.E..E..}..y..E..| +0000af40 50 01 89 55 f4 c6 00 2d f7 5d 0c 83 ec 08 ff 75 |P..U...-.].....u| +0000af50 0c ff 75 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b |..u..........E..| +0000af60 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 |E.....U..E.)....| +0000af70 c3 55 89 e5 83 ec 18 8b 4d 0c ba 67 66 66 66 89 |.U......M..gfff.| +0000af80 c8 f7 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 89 |...........)....| +0000af90 45 f4 83 7d f4 00 79 0e c7 45 f4 cc cc cc 0c c7 |E..}..y..E......| +0000afa0 45 0c 08 00 00 00 83 7d f4 00 74 14 83 ec 08 ff |E......}..t.....| +0000afb0 75 f4 ff 75 08 e8 b7 ff ff ff 83 c4 10 89 45 08 |u..u..........E.| +0000afc0 8b 4d 0c ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 |.M..gfff........| +0000afd0 c8 c1 f8 1f 29 c2 89 d0 c1 e0 02 01 d0 01 c0 29 |....)..........)| +0000afe0 c1 89 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 89 55 |......H0.E..P..U| +0000aff0 08 89 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 ec 20 |......E...U.... | +0000b000 c7 45 e3 30 31 32 33 c7 45 e7 34 35 36 37 c7 45 |.E.0123.E.4567.E| +0000b010 eb 38 39 41 42 c7 45 ef 43 44 45 46 c6 45 f3 00 |.89AB.E.CDEF.E..| +0000b020 c7 45 fc 00 00 00 00 c7 45 f8 00 00 00 00 eb 43 |.E......E......C| +0000b030 8b 45 0c 25 00 00 00 f0 89 45 f4 83 7d fc 00 75 |.E.%.....E..}..u| +0000b040 0c 83 7d f4 00 75 06 83 7d f8 07 75 1e 83 45 fc |..}..u..}..u..E.| +0000b050 01 c1 6d f4 1c 8b 45 08 8d 50 01 89 55 08 8d 4d |..m...E..P..U..M| +0000b060 e3 8b 55 f4 01 ca 0f b6 12 88 10 c1 65 0c 04 83 |..U.........e...| +0000b070 45 f8 01 83 7d f8 07 7e b7 8b 45 08 c6 00 00 8b |E...}..~..E.....| +0000b080 45 fc c9 c3 55 89 e5 83 ec 10 c7 45 f8 00 00 00 |E...U......E....| +0000b090 00 8b 45 08 89 45 f4 8b 45 0c 25 00 00 00 c0 89 |..E..E..E.%.....| +0000b0a0 45 f0 c1 6d f0 1e c7 45 fc 00 00 00 00 eb 47 83 |E..m...E......G.| +0000b0b0 7d fc 0a 74 0c 83 7d f0 00 75 06 83 7d f8 00 74 |}..t..}..u..}..t| +0000b0c0 1e c7 45 f8 01 00 00 00 83 65 f0 07 8b 45 f0 8d |..E......e...E..| +0000b0d0 48 30 8b 45 f4 8d 50 01 89 55 f4 89 ca 88 10 c1 |H0.E..P..U......| +0000b0e0 65 0c 03 8b 45 0c 25 00 00 00 e0 89 45 f0 c1 6d |e...E.%.....E..m| +0000b0f0 f0 1d 83 45 fc 01 83 7d fc 0a 7e b3 8b 45 f4 c6 |...E...}..~..E..| +0000b100 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 |...U..E.).....U.| +0000b110 e5 83 ec 18 8b 45 08 89 45 f4 83 ec 08 ff 75 0c |.....E..E.....u.| +0000b120 ff 75 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 |.u..........E..E| +0000b130 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 |.....U..E.).....| +0000b140 55 89 e5 83 ec 18 8b 45 0c ba cd cc cc cc f7 e2 |U......E........| +0000b150 89 d0 c1 e8 03 89 45 f4 83 7d f4 00 74 15 8b 45 |......E..}..t..E| +0000b160 f4 83 ec 08 50 ff 75 08 e8 04 fe ff ff 83 c4 10 |....P.u.........| +0000b170 89 45 08 8b 4d 0c ba cd cc cc cc 89 c8 f7 e2 c1 |.E..M...........| +0000b180 ea 03 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 |...........)....| +0000b190 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 |..H0.E..P..U....| +0000b1a0 10 8b 45 08 c9 c3 55 89 e5 83 ec 18 83 7d 10 00 |..E...U......}..| +0000b1b0 79 11 83 ec 0c ff 75 0c e8 4b fd ff ff 83 c4 10 |y.....u..K......| +0000b1c0 89 45 10 8b 45 14 2b 45 10 89 45 f0 83 7d f0 00 |.E..E.+E..E..}..| +0000b1d0 7e 1d 83 7d 18 00 75 17 83 ec 04 ff 75 1c ff 75 |~..}..u.....u..u| +0000b1e0 f0 ff 75 08 e8 5a 00 00 00 83 c4 10 89 45 08 c7 |..u..Z.......E..| +0000b1f0 45 f4 00 00 00 00 eb 1b 8b 55 f4 8b 45 0c 8d 0c |E........U..E...| +0000b200 02 8b 45 08 8d 50 01 89 55 08 0f b6 11 88 10 83 |..E..P..U.......| +0000b210 45 f4 01 8b 45 f4 3b 45 10 7c dd 83 7d f0 00 7e |E...E.;E.|..}..~| +0000b220 1d 83 7d 18 00 74 17 83 ec 04 ff 75 1c ff 75 f0 |..}..t.....u..u.| +0000b230 ff 75 08 e8 0b 00 00 00 83 c4 10 89 45 08 8b 45 |.u..........E..E| +0000b240 08 c9 c3 55 89 e5 eb 12 8b 45 08 8d 50 01 89 55 |...U.....E..P..U| +0000b250 08 8b 55 10 88 10 83 6d 0c 01 83 7d 0c 00 7f e8 |..U....m...}....| +0000b260 8b 45 08 5d c3 00 00 00 75 73 65 72 49 3a 20 61 |.E.]....userI: a| +0000b270 72 67 63 20 25 64 2c 20 61 72 67 73 3a 20 00 28 |rgc %d, args: .(| +0000b280 6e 75 6c 6c 29 00 20 25 73 00 0a 00 75 73 65 72 |null). %s...user| +0000b290 57 00 57 00 31 30 00 35 00 21 21 20 25 63 3a 20 |W.W.10.5.!! %c: | +0000b2a0 6b 69 6c 6c 28 25 64 29 20 73 74 61 74 75 73 20 |kill(%d) status | +0000b2b0 25 64 0a 00 3d 3d 20 25 63 3a 20 63 68 69 6c 64 |%d..== %c: child| +0000b2c0 20 25 64 20 28 25 64 29 0a 00 43 68 69 6c 64 20 | %d (%d)..Child | +0000b2d0 25 64 20 65 78 65 63 28 29 20 23 25 75 20 66 61 |%d exec() #%u fa| +0000b2e0 69 6c 65 64 0a 00 00 00 16 16 00 00 54 16 00 00 |iled........T...| +0000b2f0 a0 17 00 00 a0 17 00 00 a0 17 00 00 a0 17 00 00 |................| +* +0000b310 a0 17 00 00 a0 17 00 00 0e 17 00 00 a0 17 00 00 |................| +0000b320 a0 17 00 00 a0 17 00 00 98 16 00 00 a0 17 00 00 |................| +0000b330 4f 17 00 00 a0 17 00 00 a0 17 00 00 ca 16 00 00 |O...............| +0000b340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +0000b6e0 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +0000b6f0 03 00 01 00 00 00 00 00 94 1b 00 00 00 00 00 00 |................| +0000b700 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +0000b710 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +0000b720 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +0000b730 04 00 f1 ff 09 00 00 00 00 00 00 00 00 00 00 00 |................| +0000b740 04 00 f1 ff 11 00 00 00 00 00 00 00 00 00 00 00 |................| +0000b750 04 00 f1 ff 1a 00 00 00 00 00 00 00 00 00 00 00 |................| +0000b760 04 00 f1 ff 24 00 00 00 00 00 00 00 00 00 00 00 |....$...........| +0000b770 04 00 f1 ff 2d 00 00 00 00 00 00 00 00 00 00 00 |....-...........| +0000b780 04 00 f1 ff 36 00 00 00 00 00 00 00 00 00 00 00 |....6...........| +0000b790 04 00 f1 ff 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +0000b7a0 04 00 f1 ff 49 00 00 00 00 00 00 00 00 00 00 00 |....I...........| +0000b7b0 04 00 f1 ff 52 00 00 00 00 00 00 00 00 00 00 00 |....R...........| +0000b7c0 04 00 f1 ff 5b 00 00 00 00 00 00 00 00 00 00 00 |....[...........| +0000b7d0 04 00 f1 ff 65 00 00 00 00 00 00 00 00 00 00 00 |....e...........| +0000b7e0 04 00 f1 ff 6e 00 00 00 00 00 00 00 00 00 00 00 |....n...........| +0000b7f0 04 00 f1 ff 74 00 00 00 5e 14 00 00 21 00 00 00 |....t...^...!...| +0000b800 12 00 01 00 7d 00 00 00 cf 14 00 00 00 00 00 00 |....}...........| +0000b810 10 00 01 00 85 00 00 00 43 14 00 00 1b 00 00 00 |........C.......| +0000b820 12 00 01 00 8c 00 00 00 c2 17 00 00 72 00 00 00 |............r...| +0000b830 12 00 01 00 94 00 00 00 3a 1a 00 00 32 00 00 00 |........:...2...| +0000b840 12 00 01 00 9b 00 00 00 f7 14 00 00 00 00 00 00 |................| +0000b850 10 00 01 00 a2 00 00 00 27 15 00 00 00 00 00 00 |........'.......| +0000b860 10 00 01 00 a8 00 00 00 ac 14 00 00 1b 00 00 00 |................| +0000b870 12 00 01 00 af 00 00 00 6f 1b 00 00 22 00 00 00 |........o..."...| +0000b880 12 00 01 00 b3 00 00 00 80 13 00 00 75 00 00 00 |............u...| +0000b890 12 00 01 00 b9 00 00 00 4d 15 00 00 75 02 00 00 |........M...u...| +0000b8a0 12 00 01 00 c0 00 00 00 26 19 00 00 8a 00 00 00 |........&.......| +0000b8b0 12 00 01 00 c7 00 00 00 6c 1a 00 00 66 00 00 00 |........l...f...| +0000b8c0 12 00 01 00 86 00 00 00 ef 14 00 00 00 00 00 00 |................| +0000b8d0 10 00 01 00 cf 00 00 00 1f 15 00 00 00 00 00 00 |................| +0000b8e0 10 00 01 00 d4 00 00 00 16 14 00 00 2d 00 00 00 |............-...| +0000b8f0 12 00 01 00 dc 00 00 00 df 14 00 00 00 00 00 00 |................| +0000b900 10 00 01 00 e1 00 00 00 68 13 00 00 18 00 00 00 |........h.......| +0000b910 12 00 01 00 e6 00 00 00 7f 14 00 00 2d 00 00 00 |............-...| +0000b920 12 00 01 00 ee 00 00 00 3d 15 00 00 00 00 00 00 |........=.......| +0000b930 10 00 01 00 f5 00 00 00 e7 14 00 00 00 00 00 00 |................| +0000b940 10 00 01 00 fa 00 00 00 0f 15 00 00 00 00 00 00 |................| +0000b950 10 00 01 00 02 01 00 00 9d 18 00 00 89 00 00 00 |................| +0000b960 12 00 01 00 0a 01 00 00 d7 14 00 00 00 00 00 00 |................| +0000b970 10 00 01 00 0f 01 00 00 00 10 00 00 68 03 00 00 |............h...| +0000b980 12 00 01 00 14 01 00 00 ff 14 00 00 00 00 00 00 |................| +0000b990 10 00 01 00 1c 01 00 00 d2 1a 00 00 9d 00 00 00 |................| +0000b9a0 12 00 01 00 23 01 00 00 17 15 00 00 00 00 00 00 |....#...........| +0000b9b0 10 00 01 00 2b 01 00 00 b0 19 00 00 8a 00 00 00 |....+...........| +0000b9c0 12 00 01 00 32 01 00 00 f5 13 00 00 21 00 00 00 |....2.......!...| +0000b9d0 12 00 01 00 3b 01 00 00 07 15 00 00 00 00 00 00 |....;...........| +0000b9e0 10 00 01 00 43 01 00 00 56 18 00 00 47 00 00 00 |....C...V...G...| +0000b9f0 12 00 01 00 5c 01 00 00 c7 14 00 00 00 00 00 00 |....\...........| +0000ba00 10 00 01 00 4a 01 00 00 34 18 00 00 22 00 00 00 |....J...4..."...| +0000ba10 12 00 01 00 51 01 00 00 2f 15 00 00 00 00 00 00 |....Q.../.......| +0000ba20 10 00 01 00 57 01 00 00 37 15 00 00 00 00 00 00 |....W...7.......| +0000ba30 10 00 01 00 00 70 72 6f 67 49 2e 63 00 75 6c 69 |.....progI.c.uli| +0000ba40 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 74 |bc.c.sprint.c.st| +0000ba50 72 32 69 6e 74 2e 63 00 73 74 72 6c 65 6e 2e 63 |r2int.c.strlen.c| +0000ba60 00 63 76 74 64 65 63 2e 63 00 63 76 74 64 65 63 |.cvtdec.c.cvtdec| +0000ba70 30 2e 63 00 63 76 74 68 65 78 2e 63 00 63 76 74 |0.c.cvthex.c.cvt| +0000ba80 6f 63 74 2e 63 00 63 76 74 75 6e 73 2e 63 00 63 |oct.c.cvtuns.c.c| +0000ba90 76 74 75 6e 73 30 2e 63 00 70 61 64 73 74 72 2e |vtuns0.c.padstr.| +0000baa0 63 00 70 61 64 2e 63 00 73 77 72 69 74 65 63 68 |c.pad.c.swritech| +0000bab0 00 77 61 69 74 70 69 64 00 63 77 72 69 74 65 00 |.waitpid.cwrite.| +0000bac0 73 74 72 32 69 6e 74 00 63 76 74 75 6e 73 00 67 |str2int.cvtuns.g| +0000bad0 65 74 70 69 64 00 73 6c 65 65 70 00 73 77 72 69 |etpid.sleep.swri| +0000bae0 74 65 00 70 61 64 00 73 70 61 77 6e 00 73 70 72 |te.pad.spawn.spr| +0000baf0 69 6e 74 00 63 76 74 68 65 78 00 63 76 74 75 6e |int.cvthex.cvtun| +0000bb00 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 65 73 00 |s0.kill.cwrites.| +0000bb10 65 78 65 63 00 77 61 69 74 00 73 77 72 69 74 65 |exec.wait.swrite| +0000bb20 73 00 5f 73 74 61 72 74 00 72 65 61 64 00 67 65 |s._start.read.ge| +0000bb30 74 70 72 69 6f 00 63 76 74 64 65 63 30 00 66 6f |tprio.cvtdec0.fo| +0000bb40 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 69 64 00 |rk.main.getppid.| +0000bb50 70 61 64 73 74 72 00 73 65 74 70 72 69 6f 00 63 |padstr.setprio.c| +0000bb60 76 74 6f 63 74 00 63 77 72 69 74 65 63 68 00 67 |vtoct.cwritech.g| +0000bb70 65 74 74 69 6d 65 00 63 76 74 64 65 63 00 73 74 |ettime.cvtdec.st| +0000bb80 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 6b 65 5f |rlen.bogus.fake_| +0000bb90 65 78 69 74 00 00 2e 73 79 6d 74 61 62 00 2e 73 |exit...symtab..s| +0000bba0 74 72 74 61 62 00 2e 73 68 73 74 72 74 61 62 00 |trtab..shstrtab.| +0000bbb0 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 00 2e 64 |.text..rodata..d| +0000bbc0 61 74 61 00 2e 62 73 73 00 00 00 00 00 00 00 00 |ata..bss........| +0000bbd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +0000bbf0 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +0000bc00 00 10 00 00 74 00 00 00 91 0b 00 00 00 00 00 00 |....t...........| +0000bc10 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +0000bc20 01 00 00 00 02 00 00 00 94 1b 00 00 08 0c 00 00 |................| +0000bc30 d8 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +0000bc40 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +0000bc50 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +0000bc60 00 00 00 00 01 00 00 00 00 00 00 00 2f 00 00 00 |............/...| +0000bc70 08 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +0000bc80 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +0000bc90 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +0000bca0 00 00 00 00 74 10 00 00 60 03 00 00 06 00 00 00 |....t...`.......| +0000bcb0 12 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +0000bcc0 03 00 00 00 00 00 00 00 00 00 00 00 d4 13 00 00 |................| +0000bcd0 61 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |a...............| +0000bce0 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +0000bcf0 00 00 00 00 35 15 00 00 34 00 00 00 00 00 00 00 |....5...4.......| +0000bd00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +0000bd10 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +0000bd20 02 00 03 00 01 00 00 00 85 13 00 00 34 00 00 00 |............4...| +0000bd30 6c 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |l.......4. ...(.| +0000bd40 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +0000bd50 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +0000bd60 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +0000bd70 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +0000bd80 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +0000bd90 e5 53 51 81 ec b0 00 00 00 89 cb c7 45 f4 32 00 |.SQ.........E.2.| +0000bda0 00 00 c6 45 e7 6a 8b 03 83 f8 02 74 1e 83 f8 03 |...E.j.....t....| +0000bdb0 75 2c 8b 43 04 83 c0 08 8b 00 83 ec 08 6a 0a 50 |u,.C.........j.P| +0000bdc0 e8 c9 05 00 00 83 c4 10 89 45 f4 8b 43 04 83 c0 |.........E..C...| +0000bdd0 04 8b 00 0f b6 00 88 45 e7 e9 a4 00 00 00 83 ec |.......E........| +0000bde0 04 ff 33 68 dc 19 00 00 8d 85 67 ff ff ff 50 e8 |..3h......g...P.| +0000bdf0 25 03 00 00 83 c4 10 83 ec 0c 8d 85 67 ff ff ff |%...........g...| +0000be00 50 e8 dc 01 00 00 83 c4 10 c7 45 f0 00 00 00 00 |P.........E.....| +0000be10 eb 59 8b 03 8d 14 85 00 00 00 00 8b 43 04 01 d0 |.Y..........C...| +0000be20 8b 00 85 c0 74 12 8b 03 8d 14 85 00 00 00 00 8b |....t...........| +0000be30 43 04 01 d0 8b 00 eb 05 b8 f3 19 00 00 83 ec 04 |C...............| +0000be40 50 68 fa 19 00 00 8d 85 67 ff ff ff 50 e8 c7 02 |Ph......g...P...| +0000be50 00 00 83 c4 10 83 ec 0c 8d 85 67 ff ff ff 50 e8 |..........g...P.| +0000be60 7e 01 00 00 83 c4 10 83 45 f0 01 8b 45 f0 3b 03 |~.......E...E.;.| +0000be70 7e a0 83 ec 0c 68 fe 19 00 00 e8 63 01 00 00 83 |~....h.....c....| +0000be80 c4 10 83 ec 04 6a 01 8d 45 e7 50 6a 01 e8 29 02 |.....j..E.Pj..).| +0000be90 00 00 83 c4 10 c7 85 54 ff ff ff 00 1a 00 00 c7 |.......T........| +0000bea0 85 58 ff ff ff 06 1a 00 00 c7 85 5c ff ff ff 08 |.X.........\....| +0000beb0 1a 00 00 c7 85 60 ff ff ff 00 00 00 00 c7 45 ec |.....`........E.| +0000bec0 00 00 00 00 eb 4a 83 ec 08 8d 85 54 ff ff ff 50 |.....J.....T...P| +0000bed0 6a 12 e8 75 00 00 00 83 c4 10 89 45 e8 83 7d e8 |j..u.......E..}.| +0000bee0 00 79 16 83 ec 04 6a 03 68 0b 1a 00 00 6a 01 e8 |.y....j.h....j..| +0000bef0 c7 01 00 00 83 c4 10 eb 13 83 ec 04 6a 01 8d 45 |............j..E| +0000bf00 e7 50 6a 01 e8 b2 01 00 00 83 c4 10 83 45 ec 01 |.Pj..........E..| +0000bf10 8b 45 ec 3b 45 f4 7c ae 83 ec 0c 6a 00 e8 71 01 |.E.;E.|....j..q.| +0000bf20 00 00 83 c4 10 b8 2a 00 00 00 8d 65 f8 59 5b 5d |......*....e.Y[]| +0000bf30 8d 61 fc c3 55 89 e5 83 ec 08 83 ec 08 ff 75 08 |.a..U.........u.| +0000bf40 6a 00 e8 54 01 00 00 83 c4 10 c9 c3 55 89 e5 81 |j..T........U...| +0000bf50 ec 18 01 00 00 e8 49 01 00 00 89 45 f4 83 7d f4 |......I....E..}.| +0000bf60 00 74 05 8b 45 f4 eb 57 e8 56 01 00 00 89 45 f4 |.t..E..W.V....E.| +0000bf70 83 ec 08 ff 75 0c ff 75 08 e8 2d 01 00 00 83 c4 |....u..u..-.....| +0000bf80 10 ff 75 08 ff 75 f4 68 0f 1a 00 00 8d 85 f4 fe |..u..u.h........| +0000bf90 ff ff 50 e8 81 01 00 00 83 c4 10 83 ec 0c 8d 85 |..P.............| +0000bfa0 f4 fe ff ff 50 e8 38 00 00 00 83 c4 10 83 ec 0c |....P.8.........| +0000bfb0 6a ff e8 dc 00 00 00 83 c4 10 b8 00 00 00 00 c9 |j...............| +0000bfc0 c3 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 |.U......E..E....| +0000bfd0 6a 01 8d 45 f4 50 6a 00 e8 de 00 00 00 83 c4 10 |j..E.Pj.........| +0000bfe0 c9 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 0d |..U.........u...| +0000bff0 04 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 |.......E..E....P| +0000c000 ff 75 08 6a 00 e8 b1 00 00 00 83 c4 10 c9 c3 55 |.u.j...........U| +0000c010 89 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 00 |.........u..u.j.| +0000c020 e8 96 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 |..........U.....| +0000c030 8b 45 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a |.E..E....j..E.Pj| +0000c040 01 e8 75 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec |..u........U....| +0000c050 18 83 ec 0c ff 75 08 e8 a4 03 00 00 83 c4 10 89 |.....u..........| +0000c060 45 f4 8b 45 f4 83 ec 04 50 ff 75 08 6a 01 e8 48 |E..E....P.u.j..H| +0000c070 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec |........U.......| +0000c080 04 ff 75 0c ff 75 08 6a 01 e8 2d 00 00 00 83 c4 |..u..u.j..-.....| +0000c090 10 c9 c3 b8 00 00 00 00 cd 80 c3 b8 01 00 00 00 |................| +0000c0a0 cd 80 c3 b8 02 00 00 00 cd 80 c3 b8 03 00 00 00 |................| +0000c0b0 cd 80 c3 b8 04 00 00 00 cd 80 c3 b8 05 00 00 00 |................| +0000c0c0 cd 80 c3 b8 06 00 00 00 cd 80 c3 b8 07 00 00 00 |................| +0000c0d0 cd 80 c3 b8 08 00 00 00 cd 80 c3 b8 09 00 00 00 |................| +0000c0e0 cd 80 c3 b8 0a 00 00 00 cd 80 c3 b8 0b 00 00 00 |................| +0000c0f0 cd 80 c3 b8 0c 00 00 00 cd 80 c3 b8 ad 0b 00 00 |................| +0000c100 cd 80 c3 50 e8 8a ff ff ff e8 76 fc ff ff 83 ec |...P......v.....| +0000c110 0c 50 e8 7c ff ff ff eb fe 55 89 e5 83 ec 38 8d |.P.|.....U....8.| +0000c120 45 0c 83 c0 04 89 45 f4 e9 3f 02 00 00 80 7d f3 |E.....E..?....}.| +0000c130 25 0f 85 26 02 00 00 c7 45 ec 00 00 00 00 c7 45 |%..&....E......E| +0000c140 e4 20 00 00 00 c7 45 e8 00 00 00 00 8b 45 0c 8d |. ....E......E..| +0000c150 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 2d 75 |P..U.....E..}.-u| +0000c160 16 c7 45 ec 01 00 00 00 8b 45 0c 8d 50 01 89 55 |..E......E..P..U| +0000c170 0c 0f b6 00 88 45 f3 80 7d f3 30 75 40 c7 45 e4 |.....E..}.0u@.E.| +0000c180 30 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |0....E..P..U....| +0000c190 88 45 f3 eb 28 8b 55 e8 89 d0 c1 e0 02 01 d0 01 |.E..(.U.........| +0000c1a0 c0 89 45 e8 0f be 45 f3 83 e8 30 01 45 e8 8b 45 |..E...E...0.E..E| +0000c1b0 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 |..P..U.....E..}.| +0000c1c0 2f 7e 06 80 7d f3 39 7e cc 0f be 45 f3 83 e8 63 |/~..}.9~...E...c| +0000c1d0 83 f8 15 0f 87 93 01 00 00 8b 04 85 2c 1a 00 00 |............,...| +0000c1e0 ff e0 8b 45 f4 8d 50 04 89 55 f4 8b 00 88 45 f3 |...E..P..U....E.| +0000c1f0 0f b6 45 f3 88 45 d0 c6 45 d1 00 83 ec 08 ff 75 |..E..E..E......u| +0000c200 e4 ff 75 ec ff 75 e8 6a 01 8d 45 d0 50 ff 75 08 |..u..u.j..E.P.u.| +0000c210 e8 89 04 00 00 83 c4 20 89 45 08 e9 4c 01 00 00 |....... .E..L...| +0000c220 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d |.E..P..U......P.| +0000c230 45 d0 50 e8 ea 01 00 00 83 c4 10 89 45 e0 83 ec |E.P.........E...| +0000c240 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 |..u..u..u..u..E.| +0000c250 50 ff 75 08 e8 45 04 00 00 83 c4 20 89 45 08 e9 |P.u..E..... .E..| +0000c260 08 01 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 89 |.....E..P..U....| +0000c270 45 dc 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a ff |E.....u..u..u.j.| +0000c280 ff 75 dc ff 75 08 e8 13 04 00 00 83 c4 20 89 45 |.u..u........ .E| +0000c290 08 e9 d6 00 00 00 8b 45 f4 8d 50 04 89 55 f4 8b |.......E..P..U..| +0000c2a0 00 83 ec 08 50 8d 45 d0 50 e8 44 02 00 00 83 c4 |....P.E.P.D.....| +0000c2b0 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 |..E.....u..u..u.| +0000c2c0 ff 75 e0 8d 45 d0 50 ff 75 08 e8 cf 03 00 00 83 |.u..E.P.u.......| +0000c2d0 c4 20 89 45 08 e9 92 00 00 00 8b 45 f4 8d 50 04 |. .E.......E..P.| +0000c2e0 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 8a 02 |.U......P.E.P...| +0000c2f0 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 |......E.....u..u| +0000c300 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 8b |..u..u..E.P.u...| +0000c310 03 00 00 83 c4 20 89 45 08 eb 51 8b 45 f4 8d 50 |..... .E..Q.E..P| +0000c320 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 d3 |..U......P.E.P..| +0000c330 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff |.......E.....u..| +0000c340 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 |u..u..u..E.P.u..| +0000c350 4a 03 00 00 83 c4 20 89 45 08 90 eb 0f 8b 45 08 |J..... .E.....E.| +0000c360 8d 50 01 89 55 08 0f b6 55 f3 88 10 8b 45 0c 8d |.P..U...U....E..| +0000c370 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 00 0f |P..U.....E..}...| +0000c380 85 a8 fd ff ff 8b 45 08 c6 00 00 90 c9 c3 55 89 |......E.......U.| +0000c390 e5 53 83 ec 14 8b 45 08 8b 4d 0c bb 00 00 00 00 |.S....E..M......| +0000c3a0 c6 45 eb 39 c7 45 f8 01 00 00 00 0f b6 10 80 fa |.E.9.E..........| +0000c3b0 2d 75 0a c7 45 f8 ff ff ff ff 83 c0 01 83 f9 0a |-u..E...........| +0000c3c0 74 2b 89 ca 83 c2 2f 88 55 eb eb 21 0f b6 10 80 |t+..../.U..!....| +0000c3d0 fa 2f 7e 20 0f b6 10 38 55 eb 7c 18 0f af d9 0f |./~ ...8U.|.....| +0000c3e0 b6 10 0f be d2 01 da 8d 5a d0 83 c0 01 0f b6 10 |........Z.......| +0000c3f0 84 d2 75 d8 89 d8 0f af 45 f8 83 c4 14 5b 5d c3 |..u.....E....[].| +0000c400 55 89 e5 53 8b 55 08 bb 00 00 00 00 eb 03 83 c3 |U..S.U..........| +0000c410 01 89 d0 8d 50 01 0f b6 00 84 c0 75 f1 89 d8 5b |....P......u...[| +0000c420 5d c3 55 89 e5 83 ec 18 8b 45 08 89 45 f4 83 7d |].U......E..E..}| +0000c430 0c 00 79 0f 8b 45 f4 8d 50 01 89 55 f4 c6 00 2d |..y..E..P..U...-| +0000c440 f7 5d 0c 83 ec 08 ff 75 0c ff 75 f4 e8 18 00 00 |.].....u..u.....| +0000c450 00 83 c4 10 89 45 f4 8b 45 f4 c6 00 00 8b 55 f4 |.....E..E.....U.| +0000c460 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b |.E.).....U......| +0000c470 4d 0c ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 |M..gfff.........| +0000c480 c1 f8 1f 29 c2 89 d0 89 45 f4 83 7d f4 00 79 0e |...)....E..}..y.| +0000c490 c7 45 f4 cc cc cc 0c c7 45 0c 08 00 00 00 83 7d |.E......E......}| +0000c4a0 f4 00 74 14 83 ec 08 ff 75 f4 ff 75 08 e8 b7 ff |..t.....u..u....| +0000c4b0 ff ff 83 c4 10 89 45 08 8b 4d 0c ba 67 66 66 66 |......E..M..gfff| +0000c4c0 89 c8 f7 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 |............)...| +0000c4d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d 48 30 |.......)......H0| +0000c4e0 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 8b 45 08 |.E..P..U......E.| +0000c4f0 c9 c3 55 89 e5 83 ec 20 c7 45 e3 30 31 32 33 c7 |..U.... .E.0123.| +0000c500 45 e7 34 35 36 37 c7 45 eb 38 39 41 42 c7 45 ef |E.4567.E.89AB.E.| +0000c510 43 44 45 46 c6 45 f3 00 c7 45 fc 00 00 00 00 c7 |CDEF.E...E......| +0000c520 45 f8 00 00 00 00 eb 43 8b 45 0c 25 00 00 00 f0 |E......C.E.%....| +0000c530 89 45 f4 83 7d fc 00 75 0c 83 7d f4 00 75 06 83 |.E..}..u..}..u..| +0000c540 7d f8 07 75 1e 83 45 fc 01 c1 6d f4 1c 8b 45 08 |}..u..E...m...E.| +0000c550 8d 50 01 89 55 08 8d 4d e3 8b 55 f4 01 ca 0f b6 |.P..U..M..U.....| +0000c560 12 88 10 c1 65 0c 04 83 45 f8 01 83 7d f8 07 7e |....e...E...}..~| +0000c570 b7 8b 45 08 c6 00 00 8b 45 fc c9 c3 55 89 e5 83 |..E.....E...U...| +0000c580 ec 10 c7 45 f8 00 00 00 00 8b 45 08 89 45 f4 8b |...E......E..E..| +0000c590 45 0c 25 00 00 00 c0 89 45 f0 c1 6d f0 1e c7 45 |E.%.....E..m...E| +0000c5a0 fc 00 00 00 00 eb 47 83 7d fc 0a 74 0c 83 7d f0 |......G.}..t..}.| +0000c5b0 00 75 06 83 7d f8 00 74 1e c7 45 f8 01 00 00 00 |.u..}..t..E.....| +0000c5c0 83 65 f0 07 8b 45 f0 8d 48 30 8b 45 f4 8d 50 01 |.e...E..H0.E..P.| +0000c5d0 89 55 f4 89 ca 88 10 c1 65 0c 03 8b 45 0c 25 00 |.U......e...E.%.| +0000c5e0 00 00 e0 89 45 f0 c1 6d f0 1d 83 45 fc 01 83 7d |....E..m...E...}| +0000c5f0 fc 0a 7e b3 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 |..~..E.....U..E.| +0000c600 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b 45 08 89 |).....U......E..| +0000c610 45 f4 83 ec 08 ff 75 0c ff 75 f4 e8 18 00 00 00 |E.....u..u......| +0000c620 83 c4 10 89 45 f4 8b 45 f4 c6 00 00 8b 55 f4 8b |....E..E.....U..| +0000c630 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b 45 |E.).....U......E| +0000c640 0c ba cd cc cc cc f7 e2 89 d0 c1 e8 03 89 45 f4 |..............E.| +0000c650 83 7d f4 00 74 15 8b 45 f4 83 ec 08 50 ff 75 08 |.}..t..E....P.u.| +0000c660 e8 04 fe ff ff 83 c4 10 89 45 08 8b 4d 0c ba cd |.........E..M...| +0000c670 cc cc cc 89 c8 f7 e2 c1 ea 03 89 d0 c1 e0 02 01 |................| +0000c680 d0 01 c0 29 c1 89 ca 89 d0 8d 48 30 8b 45 08 8d |...)......H0.E..| +0000c690 50 01 89 55 08 89 ca 88 10 8b 45 08 c9 c3 55 89 |P..U......E...U.| +0000c6a0 e5 83 ec 18 83 7d 10 00 79 11 83 ec 0c ff 75 0c |.....}..y.....u.| +0000c6b0 e8 4b fd ff ff 83 c4 10 89 45 10 8b 45 14 2b 45 |.K.......E..E.+E| +0000c6c0 10 89 45 f0 83 7d f0 00 7e 1d 83 7d 18 00 75 17 |..E..}..~..}..u.| +0000c6d0 83 ec 04 ff 75 1c ff 75 f0 ff 75 08 e8 5a 00 00 |....u..u..u..Z..| +0000c6e0 00 83 c4 10 89 45 08 c7 45 f4 00 00 00 00 eb 1b |.....E..E.......| +0000c6f0 8b 55 f4 8b 45 0c 8d 0c 02 8b 45 08 8d 50 01 89 |.U..E.....E..P..| +0000c700 55 08 0f b6 11 88 10 83 45 f4 01 8b 45 f4 3b 45 |U.......E...E.;E| +0000c710 10 7c dd 83 7d f0 00 7e 1d 83 7d 18 00 74 17 83 |.|..}..~..}..t..| +0000c720 ec 04 ff 75 1c ff 75 f0 ff 75 08 e8 0b 00 00 00 |...u..u..u......| +0000c730 83 c4 10 89 45 08 8b 45 08 c9 c3 55 89 e5 eb 12 |....E..E...U....| +0000c740 8b 45 08 8d 50 01 89 55 08 8b 55 10 88 10 83 6d |.E..P..U..U....m| +0000c750 0c 01 83 7d 0c 00 7f e8 8b 45 08 5d c3 00 00 00 |...}.....E.]....| +0000c760 75 73 65 72 4a 3a 20 61 72 67 63 20 25 64 2c 20 |userJ: argc %d, | +0000c770 61 72 67 73 3a 20 00 28 6e 75 6c 6c 29 00 20 25 |args: .(null). %| +0000c780 73 00 0a 00 75 73 65 72 59 00 59 00 31 30 00 21 |s...userY.Y.10.!| +0000c790 6a 21 00 43 68 69 6c 64 20 25 64 20 65 78 65 63 |j!.Child %d exec| +0000c7a0 28 29 20 23 25 75 20 66 61 69 6c 65 64 0a 00 00 |() #%u failed...| +0000c7b0 5e 14 00 00 9c 14 00 00 e8 15 00 00 e8 15 00 00 |^...............| +0000c7c0 e8 15 00 00 e8 15 00 00 e8 15 00 00 e8 15 00 00 |................| +* +0000c7e0 56 15 00 00 e8 15 00 00 e8 15 00 00 e8 15 00 00 |V...............| +0000c7f0 e0 14 00 00 e8 15 00 00 97 15 00 00 e8 15 00 00 |................| +0000c800 e8 15 00 00 12 15 00 00 00 00 00 00 00 00 00 00 |................| +0000c810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +0000cd90 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +0000cda0 03 00 01 00 00 00 00 00 dc 19 00 00 00 00 00 00 |................| +0000cdb0 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +0000cdc0 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +0000cdd0 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +0000cde0 04 00 f1 ff 09 00 00 00 00 00 00 00 00 00 00 00 |................| +0000cdf0 04 00 f1 ff 11 00 00 00 00 00 00 00 00 00 00 00 |................| +0000ce00 04 00 f1 ff 1a 00 00 00 00 00 00 00 00 00 00 00 |................| +0000ce10 04 00 f1 ff 24 00 00 00 00 00 00 00 00 00 00 00 |....$...........| +0000ce20 04 00 f1 ff 2d 00 00 00 00 00 00 00 00 00 00 00 |....-...........| +0000ce30 04 00 f1 ff 36 00 00 00 00 00 00 00 00 00 00 00 |....6...........| +0000ce40 04 00 f1 ff 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +0000ce50 04 00 f1 ff 49 00 00 00 00 00 00 00 00 00 00 00 |....I...........| +0000ce60 04 00 f1 ff 52 00 00 00 00 00 00 00 00 00 00 00 |....R...........| +0000ce70 04 00 f1 ff 5b 00 00 00 00 00 00 00 00 00 00 00 |....[...........| +0000ce80 04 00 f1 ff 65 00 00 00 00 00 00 00 00 00 00 00 |....e...........| +0000ce90 04 00 f1 ff 6e 00 00 00 00 00 00 00 00 00 00 00 |....n...........| +0000cea0 04 00 f1 ff 74 00 00 00 a6 12 00 00 21 00 00 00 |....t.......!...| +0000ceb0 12 00 01 00 7d 00 00 00 17 13 00 00 00 00 00 00 |....}...........| +0000cec0 10 00 01 00 85 00 00 00 8b 12 00 00 1b 00 00 00 |................| +0000ced0 12 00 01 00 8c 00 00 00 0a 16 00 00 72 00 00 00 |............r...| +0000cee0 12 00 01 00 94 00 00 00 82 18 00 00 32 00 00 00 |............2...| +0000cef0 12 00 01 00 9b 00 00 00 3f 13 00 00 00 00 00 00 |........?.......| +0000cf00 10 00 01 00 a2 00 00 00 6f 13 00 00 00 00 00 00 |........o.......| +0000cf10 10 00 01 00 a8 00 00 00 f4 12 00 00 1b 00 00 00 |................| +0000cf20 12 00 01 00 af 00 00 00 b7 19 00 00 22 00 00 00 |............"...| +0000cf30 12 00 01 00 b3 00 00 00 c8 11 00 00 75 00 00 00 |............u...| +0000cf40 12 00 01 00 b9 00 00 00 95 13 00 00 75 02 00 00 |............u...| +0000cf50 12 00 01 00 c0 00 00 00 6e 17 00 00 8a 00 00 00 |........n.......| +0000cf60 12 00 01 00 c7 00 00 00 b4 18 00 00 66 00 00 00 |............f...| +0000cf70 12 00 01 00 86 00 00 00 37 13 00 00 00 00 00 00 |........7.......| +0000cf80 10 00 01 00 cf 00 00 00 67 13 00 00 00 00 00 00 |........g.......| +0000cf90 10 00 01 00 d4 00 00 00 5e 12 00 00 2d 00 00 00 |........^...-...| +0000cfa0 12 00 01 00 dc 00 00 00 27 13 00 00 00 00 00 00 |........'.......| +0000cfb0 10 00 01 00 e1 00 00 00 b0 11 00 00 18 00 00 00 |................| +0000cfc0 12 00 01 00 e6 00 00 00 c7 12 00 00 2d 00 00 00 |............-...| +0000cfd0 12 00 01 00 ee 00 00 00 85 13 00 00 00 00 00 00 |................| +0000cfe0 10 00 01 00 f5 00 00 00 2f 13 00 00 00 00 00 00 |......../.......| +0000cff0 10 00 01 00 fa 00 00 00 57 13 00 00 00 00 00 00 |........W.......| +0000d000 10 00 01 00 02 01 00 00 e5 16 00 00 89 00 00 00 |................| +0000d010 12 00 01 00 0a 01 00 00 1f 13 00 00 00 00 00 00 |................| +0000d020 10 00 01 00 0f 01 00 00 00 10 00 00 b0 01 00 00 |................| +0000d030 12 00 01 00 14 01 00 00 47 13 00 00 00 00 00 00 |........G.......| +0000d040 10 00 01 00 1c 01 00 00 1a 19 00 00 9d 00 00 00 |................| +0000d050 12 00 01 00 23 01 00 00 5f 13 00 00 00 00 00 00 |....#..._.......| +0000d060 10 00 01 00 2b 01 00 00 f8 17 00 00 8a 00 00 00 |....+...........| +0000d070 12 00 01 00 32 01 00 00 3d 12 00 00 21 00 00 00 |....2...=...!...| +0000d080 12 00 01 00 3b 01 00 00 4f 13 00 00 00 00 00 00 |....;...O.......| +0000d090 10 00 01 00 43 01 00 00 9e 16 00 00 47 00 00 00 |....C.......G...| +0000d0a0 12 00 01 00 5c 01 00 00 0f 13 00 00 00 00 00 00 |....\...........| +0000d0b0 10 00 01 00 4a 01 00 00 7c 16 00 00 22 00 00 00 |....J...|..."...| +0000d0c0 12 00 01 00 51 01 00 00 77 13 00 00 00 00 00 00 |....Q...w.......| +0000d0d0 10 00 01 00 57 01 00 00 7f 13 00 00 00 00 00 00 |....W...........| +0000d0e0 10 00 01 00 00 70 72 6f 67 4a 2e 63 00 75 6c 69 |.....progJ.c.uli| +0000d0f0 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 74 |bc.c.sprint.c.st| +0000d100 72 32 69 6e 74 2e 63 00 73 74 72 6c 65 6e 2e 63 |r2int.c.strlen.c| +0000d110 00 63 76 74 64 65 63 2e 63 00 63 76 74 64 65 63 |.cvtdec.c.cvtdec| +0000d120 30 2e 63 00 63 76 74 68 65 78 2e 63 00 63 76 74 |0.c.cvthex.c.cvt| +0000d130 6f 63 74 2e 63 00 63 76 74 75 6e 73 2e 63 00 63 |oct.c.cvtuns.c.c| +0000d140 76 74 75 6e 73 30 2e 63 00 70 61 64 73 74 72 2e |vtuns0.c.padstr.| +0000d150 63 00 70 61 64 2e 63 00 73 77 72 69 74 65 63 68 |c.pad.c.swritech| +0000d160 00 77 61 69 74 70 69 64 00 63 77 72 69 74 65 00 |.waitpid.cwrite.| +0000d170 73 74 72 32 69 6e 74 00 63 76 74 75 6e 73 00 67 |str2int.cvtuns.g| +0000d180 65 74 70 69 64 00 73 6c 65 65 70 00 73 77 72 69 |etpid.sleep.swri| +0000d190 74 65 00 70 61 64 00 73 70 61 77 6e 00 73 70 72 |te.pad.spawn.spr| +0000d1a0 69 6e 74 00 63 76 74 68 65 78 00 63 76 74 75 6e |int.cvthex.cvtun| +0000d1b0 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 65 73 00 |s0.kill.cwrites.| +0000d1c0 65 78 65 63 00 77 61 69 74 00 73 77 72 69 74 65 |exec.wait.swrite| +0000d1d0 73 00 5f 73 74 61 72 74 00 72 65 61 64 00 67 65 |s._start.read.ge| +0000d1e0 74 70 72 69 6f 00 63 76 74 64 65 63 30 00 66 6f |tprio.cvtdec0.fo| +0000d1f0 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 69 64 00 |rk.main.getppid.| +0000d200 70 61 64 73 74 72 00 73 65 74 70 72 69 6f 00 63 |padstr.setprio.c| +0000d210 76 74 6f 63 74 00 63 77 72 69 74 65 63 68 00 67 |vtoct.cwritech.g| +0000d220 65 74 74 69 6d 65 00 63 76 74 64 65 63 00 73 74 |ettime.cvtdec.st| +0000d230 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 6b 65 5f |rlen.bogus.fake_| +0000d240 65 78 69 74 00 00 2e 73 79 6d 74 61 62 00 2e 73 |exit...symtab..s| +0000d250 74 72 74 61 62 00 2e 73 68 73 74 72 74 61 62 00 |trtab..shstrtab.| +0000d260 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 00 2e 64 |.text..rodata..d| +0000d270 61 74 61 00 2e 62 73 73 00 00 00 00 00 00 00 00 |ata..bss........| +0000d280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +0000d2a0 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +0000d2b0 00 10 00 00 74 00 00 00 d9 09 00 00 00 00 00 00 |....t...........| +0000d2c0 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +0000d2d0 01 00 00 00 02 00 00 00 dc 19 00 00 50 0a 00 00 |............P...| +0000d2e0 a8 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +0000d2f0 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +0000d300 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +0000d310 00 00 00 00 01 00 00 00 00 00 00 00 2f 00 00 00 |............/...| +0000d320 08 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +0000d330 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +0000d340 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +0000d350 00 00 00 00 74 10 00 00 60 03 00 00 06 00 00 00 |....t...`.......| +0000d360 12 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +0000d370 03 00 00 00 00 00 00 00 00 00 00 00 d4 13 00 00 |................| +0000d380 61 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |a...............| +0000d390 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +0000d3a0 00 00 00 00 35 15 00 00 34 00 00 00 00 00 00 00 |....5...4.......| +0000d3b0 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +0000d3c0 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +0000d3d0 02 00 03 00 01 00 00 00 b9 13 00 00 34 00 00 00 |............4...| +0000d3e0 6c 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |l.......4. ...(.| +0000d3f0 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +0000d400 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +0000d410 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +0000d420 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +0000d430 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +0000d440 e5 53 51 83 ec 50 89 cb c7 45 f4 05 00 00 00 c6 |.SQ..P...E......| +0000d450 45 e3 34 c7 45 e8 1e 00 00 00 c7 45 df 2a 34 2a |E.4.E......E.*4*| +0000d460 00 8b 03 83 f8 02 74 1e 83 f8 03 75 2c 8b 43 04 |......t....u,.C.| +0000d470 83 c0 08 8b 00 83 ec 08 6a 0a 50 e8 f2 05 00 00 |........j.P.....| +0000d480 83 c4 10 89 45 f4 8b 43 04 83 c0 04 8b 00 0f b6 |....E..C........| +0000d490 00 88 45 e3 e9 98 00 00 00 83 ec 04 ff 33 68 10 |..E..........3h.| +0000d4a0 1a 00 00 8d 45 bf 50 e8 51 03 00 00 83 c4 10 83 |....E.P.Q.......| +0000d4b0 ec 0c 8d 45 bf 50 e8 0b 02 00 00 83 c4 10 c7 45 |...E.P.........E| +0000d4c0 f0 00 00 00 00 eb 53 8b 03 8d 14 85 00 00 00 00 |......S.........| +0000d4d0 8b 43 04 01 d0 8b 00 85 c0 74 12 8b 03 8d 14 85 |.C.......t......| +0000d4e0 00 00 00 00 8b 43 04 01 d0 8b 00 eb 05 b8 27 1a |.....C........'.| +0000d4f0 00 00 83 ec 04 50 68 2e 1a 00 00 8d 45 bf 50 e8 |.....Ph.....E.P.| +0000d500 f9 02 00 00 83 c4 10 83 ec 0c 8d 45 bf 50 e8 b3 |...........E.P..| +0000d510 01 00 00 83 c4 10 83 45 f0 01 8b 45 f0 3b 03 7e |.......E...E.;.~| +0000d520 a6 83 ec 0c 68 32 1a 00 00 e8 98 01 00 00 83 c4 |....h2..........| +0000d530 10 83 ec 04 6a 01 8d 45 e3 50 6a 01 e8 5e 02 00 |....j..E.Pj..^..| +0000d540 00 83 c4 10 c7 45 ac 34 1a 00 00 c7 45 b0 3a 1a |.....E.4....E.:.| +0000d550 00 00 8d 45 bf 89 45 b4 c7 45 b8 00 00 00 00 c7 |...E..E..E......| +0000d560 45 ec 00 00 00 00 e9 85 00 00 00 83 ec 04 6a 01 |E.............j.| +0000d570 8d 45 e3 50 6a 01 e8 24 02 00 00 83 c4 10 8b 45 |.E.Pj..$.......E| +0000d580 ec 83 c0 64 83 ec 04 50 68 3c 1a 00 00 8d 45 bf |...d...Ph<....E.| +0000d590 50 e8 67 02 00 00 83 c4 10 83 ec 08 8d 45 ac 50 |P.g..........E.P| +0000d5a0 6a 11 e8 89 00 00 00 83 c4 10 89 45 e4 83 7d e4 |j..........E..}.| +0000d5b0 00 79 11 83 ec 0c 8d 45 df 50 e8 70 01 00 00 83 |.y.....E.P.p....| +0000d5c0 c4 10 eb 13 83 ec 04 6a 01 8d 45 e3 50 6a 01 e8 |.......j..E.Pj..| +0000d5d0 cb 01 00 00 83 c4 10 8b 45 e8 69 c0 e8 03 00 00 |........E.i.....| +0000d5e0 83 ec 0c 50 e8 ee 01 00 00 83 c4 10 83 45 ec 01 |...P.........E..| +0000d5f0 8b 45 ec 3b 45 f4 0f 8c 6f ff ff ff 83 ec 0c 6a |.E.;E...o......j| +0000d600 00 e8 71 01 00 00 83 c4 10 b8 2a 00 00 00 8d 65 |..q.......*....e| +0000d610 f8 59 5b 5d 8d 61 fc c3 55 89 e5 83 ec 08 83 ec |.Y[].a..U.......| +0000d620 08 ff 75 08 6a 00 e8 54 01 00 00 83 c4 10 c9 c3 |..u.j..T........| +0000d630 55 89 e5 81 ec 18 01 00 00 e8 49 01 00 00 89 45 |U.........I....E| +0000d640 f4 83 7d f4 00 74 05 8b 45 f4 eb 57 e8 56 01 00 |..}..t..E..W.V..| +0000d650 00 89 45 f4 83 ec 08 ff 75 0c ff 75 08 e8 2d 01 |..E.....u..u..-.| +0000d660 00 00 83 c4 10 ff 75 08 ff 75 f4 68 3f 1a 00 00 |......u..u.h?...| +0000d670 8d 85 f4 fe ff ff 50 e8 81 01 00 00 83 c4 10 83 |......P.........| +0000d680 ec 0c 8d 85 f4 fe ff ff 50 e8 38 00 00 00 83 c4 |........P.8.....| +0000d690 10 83 ec 0c 6a ff e8 dc 00 00 00 83 c4 10 b8 00 |....j...........| +0000d6a0 00 00 00 c9 c3 55 89 e5 83 ec 18 8b 45 08 88 45 |.....U......E..E| +0000d6b0 f4 83 ec 04 6a 01 8d 45 f4 50 6a 00 e8 de 00 00 |....j..E.Pj.....| +0000d6c0 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 ec 0c ff |......U.........| +0000d6d0 75 08 e8 0d 04 00 00 83 c4 10 89 45 f4 8b 45 f4 |u..........E..E.| +0000d6e0 83 ec 04 50 ff 75 08 6a 00 e8 b1 00 00 00 83 c4 |...P.u.j........| +0000d6f0 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff 75 0c ff |...U.........u..| +0000d700 75 08 6a 00 e8 96 00 00 00 83 c4 10 c9 c3 55 89 |u.j...........U.| +0000d710 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 6a 01 8d |.....E..E....j..| +0000d720 45 f4 50 6a 01 e8 75 00 00 00 83 c4 10 c9 c3 55 |E.Pj..u........U| +0000d730 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 a4 03 00 00 |.........u......| +0000d740 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 ff 75 08 |....E..E....P.u.| +0000d750 6a 01 e8 48 00 00 00 83 c4 10 c9 c3 55 89 e5 83 |j..H........U...| +0000d760 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 01 e8 2d 00 |......u..u.j..-.| +0000d770 00 00 83 c4 10 c9 c3 b8 00 00 00 00 cd 80 c3 b8 |................| +0000d780 01 00 00 00 cd 80 c3 b8 02 00 00 00 cd 80 c3 b8 |................| +0000d790 03 00 00 00 cd 80 c3 b8 04 00 00 00 cd 80 c3 b8 |................| +0000d7a0 05 00 00 00 cd 80 c3 b8 06 00 00 00 cd 80 c3 b8 |................| +0000d7b0 07 00 00 00 cd 80 c3 b8 08 00 00 00 cd 80 c3 b8 |................| +0000d7c0 09 00 00 00 cd 80 c3 b8 0a 00 00 00 cd 80 c3 b8 |................| +0000d7d0 0b 00 00 00 cd 80 c3 b8 0c 00 00 00 cd 80 c3 b8 |................| +0000d7e0 ad 0b 00 00 cd 80 c3 50 e8 8a ff ff ff e8 42 fc |.......P......B.| +0000d7f0 ff ff 83 ec 0c 50 e8 7c ff ff ff eb fe 55 89 e5 |.....P.|.....U..| +0000d800 83 ec 38 8d 45 0c 83 c0 04 89 45 f4 e9 3f 02 00 |..8.E.....E..?..| +0000d810 00 80 7d f3 25 0f 85 26 02 00 00 c7 45 ec 00 00 |..}.%..&....E...| +0000d820 00 00 c7 45 e4 20 00 00 00 c7 45 e8 00 00 00 00 |...E. ....E.....| +0000d830 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 |.E..P..U.....E..| +0000d840 7d f3 2d 75 16 c7 45 ec 01 00 00 00 8b 45 0c 8d |}.-u..E......E..| +0000d850 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 30 75 |P..U.....E..}.0u| +0000d860 40 c7 45 e4 30 00 00 00 8b 45 0c 8d 50 01 89 55 |@.E.0....E..P..U| +0000d870 0c 0f b6 00 88 45 f3 eb 28 8b 55 e8 89 d0 c1 e0 |.....E..(.U.....| +0000d880 02 01 d0 01 c0 89 45 e8 0f be 45 f3 83 e8 30 01 |......E...E...0.| +0000d890 45 e8 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |E..E..P..U.....E| +0000d8a0 f3 80 7d f3 2f 7e 06 80 7d f3 39 7e cc 0f be 45 |..}./~..}.9~...E| +0000d8b0 f3 83 e8 63 83 f8 15 0f 87 93 01 00 00 8b 04 85 |...c............| +0000d8c0 5c 1a 00 00 ff e0 8b 45 f4 8d 50 04 89 55 f4 8b |\......E..P..U..| +0000d8d0 00 88 45 f3 0f b6 45 f3 88 45 d0 c6 45 d1 00 83 |..E...E..E..E...| +0000d8e0 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a 01 8d 45 d0 |...u..u..u.j..E.| +0000d8f0 50 ff 75 08 e8 89 04 00 00 83 c4 20 89 45 08 e9 |P.u........ .E..| +0000d900 4c 01 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 |L....E..P..U....| +0000d910 ec 08 50 8d 45 d0 50 e8 ea 01 00 00 83 c4 10 89 |..P.E.P.........| +0000d920 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 |E.....u..u..u..u| +0000d930 e0 8d 45 d0 50 ff 75 08 e8 45 04 00 00 83 c4 20 |..E.P.u..E..... | +0000d940 89 45 08 e9 08 01 00 00 8b 45 f4 8d 50 04 89 55 |.E.......E..P..U| +0000d950 f4 8b 00 89 45 dc 83 ec 08 ff 75 e4 ff 75 ec ff |....E.....u..u..| +0000d960 75 e8 6a ff ff 75 dc ff 75 08 e8 13 04 00 00 83 |u.j..u..u.......| +0000d970 c4 20 89 45 08 e9 d6 00 00 00 8b 45 f4 8d 50 04 |. .E.......E..P.| +0000d980 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 44 02 |.U......P.E.P.D.| +0000d990 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 |......E.....u..u| +0000d9a0 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 cf |..u..u..E.P.u...| +0000d9b0 03 00 00 83 c4 20 89 45 08 e9 92 00 00 00 8b 45 |..... .E.......E| +0000d9c0 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 |..P..U......P.E.| +0000d9d0 50 e8 8a 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff |P.........E.....| +0000d9e0 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff |u..u..u..u..E.P.| +0000d9f0 75 08 e8 8b 03 00 00 83 c4 20 89 45 08 eb 51 8b |u........ .E..Q.| +0000da00 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 |E..P..U......P.E| +0000da10 d0 50 e8 d3 02 00 00 83 c4 10 89 45 e0 83 ec 08 |.P.........E....| +0000da20 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 |.u..u..u..u..E.P| +0000da30 ff 75 08 e8 4a 03 00 00 83 c4 20 89 45 08 90 eb |.u..J..... .E...| +0000da40 0f 8b 45 08 8d 50 01 89 55 08 0f b6 55 f3 88 10 |..E..P..U...U...| +0000da50 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 |.E..P..U.....E..| +0000da60 7d f3 00 0f 85 a8 fd ff ff 8b 45 08 c6 00 00 90 |}.........E.....| +0000da70 c9 c3 55 89 e5 53 83 ec 14 8b 45 08 8b 4d 0c bb |..U..S....E..M..| +0000da80 00 00 00 00 c6 45 eb 39 c7 45 f8 01 00 00 00 0f |.....E.9.E......| +0000da90 b6 10 80 fa 2d 75 0a c7 45 f8 ff ff ff ff 83 c0 |....-u..E.......| +0000daa0 01 83 f9 0a 74 2b 89 ca 83 c2 2f 88 55 eb eb 21 |....t+..../.U..!| +0000dab0 0f b6 10 80 fa 2f 7e 20 0f b6 10 38 55 eb 7c 18 |...../~ ...8U.|.| +0000dac0 0f af d9 0f b6 10 0f be d2 01 da 8d 5a d0 83 c0 |............Z...| +0000dad0 01 0f b6 10 84 d2 75 d8 89 d8 0f af 45 f8 83 c4 |......u.....E...| +0000dae0 14 5b 5d c3 55 89 e5 53 8b 55 08 bb 00 00 00 00 |.[].U..S.U......| +0000daf0 eb 03 83 c3 01 89 d0 8d 50 01 0f b6 00 84 c0 75 |........P......u| +0000db00 f1 89 d8 5b 5d c3 55 89 e5 83 ec 18 8b 45 08 89 |...[].U......E..| +0000db10 45 f4 83 7d 0c 00 79 0f 8b 45 f4 8d 50 01 89 55 |E..}..y..E..P..U| +0000db20 f4 c6 00 2d f7 5d 0c 83 ec 08 ff 75 0c ff 75 f4 |...-.].....u..u.| +0000db30 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 00 |.........E..E...| +0000db40 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 |..U..E.).....U..| +0000db50 83 ec 18 8b 4d 0c ba 67 66 66 66 89 c8 f7 ea c1 |....M..gfff.....| +0000db60 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 89 45 f4 83 7d |.......)....E..}| +0000db70 f4 00 79 0e c7 45 f4 cc cc cc 0c c7 45 0c 08 00 |..y..E......E...| +0000db80 00 00 83 7d f4 00 74 14 83 ec 08 ff 75 f4 ff 75 |...}..t.....u..u| +0000db90 08 e8 b7 ff ff ff 83 c4 10 89 45 08 8b 4d 0c ba |..........E..M..| +0000dba0 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 f8 1f |gfff............| +0000dbb0 29 c2 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 |)..........)....| +0000dbc0 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 |..H0.E..P..U....| +0000dbd0 10 8b 45 08 c9 c3 55 89 e5 83 ec 20 c7 45 e3 30 |..E...U.... .E.0| +0000dbe0 31 32 33 c7 45 e7 34 35 36 37 c7 45 eb 38 39 41 |123.E.4567.E.89A| +0000dbf0 42 c7 45 ef 43 44 45 46 c6 45 f3 00 c7 45 fc 00 |B.E.CDEF.E...E..| +0000dc00 00 00 00 c7 45 f8 00 00 00 00 eb 43 8b 45 0c 25 |....E......C.E.%| +0000dc10 00 00 00 f0 89 45 f4 83 7d fc 00 75 0c 83 7d f4 |.....E..}..u..}.| +0000dc20 00 75 06 83 7d f8 07 75 1e 83 45 fc 01 c1 6d f4 |.u..}..u..E...m.| +0000dc30 1c 8b 45 08 8d 50 01 89 55 08 8d 4d e3 8b 55 f4 |..E..P..U..M..U.| +0000dc40 01 ca 0f b6 12 88 10 c1 65 0c 04 83 45 f8 01 83 |........e...E...| +0000dc50 7d f8 07 7e b7 8b 45 08 c6 00 00 8b 45 fc c9 c3 |}..~..E.....E...| +0000dc60 55 89 e5 83 ec 10 c7 45 f8 00 00 00 00 8b 45 08 |U......E......E.| +0000dc70 89 45 f4 8b 45 0c 25 00 00 00 c0 89 45 f0 c1 6d |.E..E.%.....E..m| +0000dc80 f0 1e c7 45 fc 00 00 00 00 eb 47 83 7d fc 0a 74 |...E......G.}..t| +0000dc90 0c 83 7d f0 00 75 06 83 7d f8 00 74 1e c7 45 f8 |..}..u..}..t..E.| +0000dca0 01 00 00 00 83 65 f0 07 8b 45 f0 8d 48 30 8b 45 |.....e...E..H0.E| +0000dcb0 f4 8d 50 01 89 55 f4 89 ca 88 10 c1 65 0c 03 8b |..P..U......e...| +0000dcc0 45 0c 25 00 00 00 e0 89 45 f0 c1 6d f0 1d 83 45 |E.%.....E..m...E| +0000dcd0 fc 01 83 7d fc 0a 7e b3 8b 45 f4 c6 00 00 8b 55 |...}..~..E.....U| +0000dce0 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 |..E.).....U.....| +0000dcf0 8b 45 08 89 45 f4 83 ec 08 ff 75 0c ff 75 f4 e8 |.E..E.....u..u..| +0000dd00 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 00 00 |........E..E....| +0000dd10 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 |.U..E.).....U...| +0000dd20 ec 18 8b 45 0c ba cd cc cc cc f7 e2 89 d0 c1 e8 |...E............| +0000dd30 03 89 45 f4 83 7d f4 00 74 15 8b 45 f4 83 ec 08 |..E..}..t..E....| +0000dd40 50 ff 75 08 e8 04 fe ff ff 83 c4 10 89 45 08 8b |P.u..........E..| +0000dd50 4d 0c ba cd cc cc cc 89 c8 f7 e2 c1 ea 03 89 d0 |M...............| +0000dd60 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d 48 30 |.......)......H0| +0000dd70 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 8b 45 08 |.E..P..U......E.| +0000dd80 c9 c3 55 89 e5 83 ec 18 83 7d 10 00 79 11 83 ec |..U......}..y...| +0000dd90 0c ff 75 0c e8 4b fd ff ff 83 c4 10 89 45 10 8b |..u..K.......E..| +0000dda0 45 14 2b 45 10 89 45 f0 83 7d f0 00 7e 1d 83 7d |E.+E..E..}..~..}| +0000ddb0 18 00 75 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 08 |..u.....u..u..u.| +0000ddc0 e8 5a 00 00 00 83 c4 10 89 45 08 c7 45 f4 00 00 |.Z.......E..E...| +0000ddd0 00 00 eb 1b 8b 55 f4 8b 45 0c 8d 0c 02 8b 45 08 |.....U..E.....E.| +0000dde0 8d 50 01 89 55 08 0f b6 11 88 10 83 45 f4 01 8b |.P..U.......E...| +0000ddf0 45 f4 3b 45 10 7c dd 83 7d f0 00 7e 1d 83 7d 18 |E.;E.|..}..~..}.| +0000de00 00 74 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 08 e8 |.t.....u..u..u..| +0000de10 0b 00 00 00 83 c4 10 89 45 08 8b 45 08 c9 c3 55 |........E..E...U| +0000de20 89 e5 eb 12 8b 45 08 8d 50 01 89 55 08 8b 55 10 |.....E..P..U..U.| +0000de30 88 10 83 6d 0c 01 83 7d 0c 00 7f e8 8b 45 08 5d |...m...}.....E.]| +0000de40 c3 00 00 00 6d 61 69 6e 34 3a 20 61 72 67 63 20 |....main4: argc | +0000de50 25 64 2c 20 61 72 67 73 3a 20 00 28 6e 75 6c 6c |%d, args: .(null| +0000de60 29 00 20 25 73 00 0a 00 75 73 65 72 58 00 58 00 |). %s...userX.X.| +0000de70 25 64 00 43 68 69 6c 64 20 25 64 20 65 78 65 63 |%d.Child %d exec| +0000de80 28 29 20 23 25 75 20 66 61 69 6c 65 64 0a 00 00 |() #%u failed...| +0000de90 92 14 00 00 d0 14 00 00 1c 16 00 00 1c 16 00 00 |................| +0000dea0 1c 16 00 00 1c 16 00 00 1c 16 00 00 1c 16 00 00 |................| +* +0000dec0 8a 15 00 00 1c 16 00 00 1c 16 00 00 1c 16 00 00 |................| +0000ded0 14 15 00 00 1c 16 00 00 cb 15 00 00 1c 16 00 00 |................| +0000dee0 1c 16 00 00 46 15 00 00 00 00 00 00 00 00 00 00 |....F...........| +0000def0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +0000e440 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +0000e450 03 00 01 00 00 00 00 00 10 1a 00 00 00 00 00 00 |................| +0000e460 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +0000e470 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +0000e480 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +0000e490 04 00 f1 ff 0a 00 00 00 00 00 00 00 00 00 00 00 |................| +0000e4a0 04 00 f1 ff 12 00 00 00 00 00 00 00 00 00 00 00 |................| +0000e4b0 04 00 f1 ff 1b 00 00 00 00 00 00 00 00 00 00 00 |................| +0000e4c0 04 00 f1 ff 25 00 00 00 00 00 00 00 00 00 00 00 |....%...........| +0000e4d0 04 00 f1 ff 2e 00 00 00 00 00 00 00 00 00 00 00 |................| +0000e4e0 04 00 f1 ff 37 00 00 00 00 00 00 00 00 00 00 00 |....7...........| +0000e4f0 04 00 f1 ff 41 00 00 00 00 00 00 00 00 00 00 00 |....A...........| +0000e500 04 00 f1 ff 4a 00 00 00 00 00 00 00 00 00 00 00 |....J...........| +0000e510 04 00 f1 ff 53 00 00 00 00 00 00 00 00 00 00 00 |....S...........| +0000e520 04 00 f1 ff 5c 00 00 00 00 00 00 00 00 00 00 00 |....\...........| +0000e530 04 00 f1 ff 66 00 00 00 00 00 00 00 00 00 00 00 |....f...........| +0000e540 04 00 f1 ff 6f 00 00 00 00 00 00 00 00 00 00 00 |....o...........| +0000e550 04 00 f1 ff 75 00 00 00 da 12 00 00 21 00 00 00 |....u.......!...| +0000e560 12 00 01 00 7e 00 00 00 4b 13 00 00 00 00 00 00 |....~...K.......| +0000e570 10 00 01 00 86 00 00 00 bf 12 00 00 1b 00 00 00 |................| +0000e580 12 00 01 00 8d 00 00 00 3e 16 00 00 72 00 00 00 |........>...r...| +0000e590 12 00 01 00 95 00 00 00 b6 18 00 00 32 00 00 00 |............2...| +0000e5a0 12 00 01 00 9c 00 00 00 73 13 00 00 00 00 00 00 |........s.......| +0000e5b0 10 00 01 00 a3 00 00 00 a3 13 00 00 00 00 00 00 |................| +0000e5c0 10 00 01 00 a9 00 00 00 28 13 00 00 1b 00 00 00 |........(.......| +0000e5d0 12 00 01 00 b0 00 00 00 eb 19 00 00 22 00 00 00 |............"...| +0000e5e0 12 00 01 00 b4 00 00 00 fc 11 00 00 75 00 00 00 |............u...| +0000e5f0 12 00 01 00 ba 00 00 00 c9 13 00 00 75 02 00 00 |............u...| +0000e600 12 00 01 00 c1 00 00 00 a2 17 00 00 8a 00 00 00 |................| +0000e610 12 00 01 00 c8 00 00 00 e8 18 00 00 66 00 00 00 |............f...| +0000e620 12 00 01 00 87 00 00 00 6b 13 00 00 00 00 00 00 |........k.......| +0000e630 10 00 01 00 d0 00 00 00 9b 13 00 00 00 00 00 00 |................| +0000e640 10 00 01 00 d5 00 00 00 92 12 00 00 2d 00 00 00 |............-...| +0000e650 12 00 01 00 dd 00 00 00 5b 13 00 00 00 00 00 00 |........[.......| +0000e660 10 00 01 00 e2 00 00 00 e4 11 00 00 18 00 00 00 |................| +0000e670 12 00 01 00 e7 00 00 00 fb 12 00 00 2d 00 00 00 |............-...| +0000e680 12 00 01 00 ef 00 00 00 b9 13 00 00 00 00 00 00 |................| +0000e690 10 00 01 00 f6 00 00 00 63 13 00 00 00 00 00 00 |........c.......| +0000e6a0 10 00 01 00 fb 00 00 00 8b 13 00 00 00 00 00 00 |................| +0000e6b0 10 00 01 00 03 01 00 00 19 17 00 00 89 00 00 00 |................| +0000e6c0 12 00 01 00 0b 01 00 00 53 13 00 00 00 00 00 00 |........S.......| +0000e6d0 10 00 01 00 10 01 00 00 00 10 00 00 e4 01 00 00 |................| +0000e6e0 12 00 01 00 15 01 00 00 7b 13 00 00 00 00 00 00 |........{.......| +0000e6f0 10 00 01 00 1d 01 00 00 4e 19 00 00 9d 00 00 00 |........N.......| +0000e700 12 00 01 00 24 01 00 00 93 13 00 00 00 00 00 00 |....$...........| +0000e710 10 00 01 00 2c 01 00 00 2c 18 00 00 8a 00 00 00 |....,...,.......| +0000e720 12 00 01 00 33 01 00 00 71 12 00 00 21 00 00 00 |....3...q...!...| +0000e730 12 00 01 00 3c 01 00 00 83 13 00 00 00 00 00 00 |....<...........| +0000e740 10 00 01 00 44 01 00 00 d2 16 00 00 47 00 00 00 |....D.......G...| +0000e750 12 00 01 00 5d 01 00 00 43 13 00 00 00 00 00 00 |....]...C.......| +0000e760 10 00 01 00 4b 01 00 00 b0 16 00 00 22 00 00 00 |....K......."...| +0000e770 12 00 01 00 52 01 00 00 ab 13 00 00 00 00 00 00 |....R...........| +0000e780 10 00 01 00 58 01 00 00 b3 13 00 00 00 00 00 00 |....X...........| +0000e790 10 00 01 00 00 70 72 6f 67 4b 4c 2e 63 00 75 6c |.....progKL.c.ul| +0000e7a0 69 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 |ibc.c.sprint.c.s| +0000e7b0 74 72 32 69 6e 74 2e 63 00 73 74 72 6c 65 6e 2e |tr2int.c.strlen.| +0000e7c0 63 00 63 76 74 64 65 63 2e 63 00 63 76 74 64 65 |c.cvtdec.c.cvtde| +0000e7d0 63 30 2e 63 00 63 76 74 68 65 78 2e 63 00 63 76 |c0.c.cvthex.c.cv| +0000e7e0 74 6f 63 74 2e 63 00 63 76 74 75 6e 73 2e 63 00 |toct.c.cvtuns.c.| +0000e7f0 63 76 74 75 6e 73 30 2e 63 00 70 61 64 73 74 72 |cvtuns0.c.padstr| +0000e800 2e 63 00 70 61 64 2e 63 00 73 77 72 69 74 65 63 |.c.pad.c.swritec| +0000e810 68 00 77 61 69 74 70 69 64 00 63 77 72 69 74 65 |h.waitpid.cwrite| +0000e820 00 73 74 72 32 69 6e 74 00 63 76 74 75 6e 73 00 |.str2int.cvtuns.| +0000e830 67 65 74 70 69 64 00 73 6c 65 65 70 00 73 77 72 |getpid.sleep.swr| +0000e840 69 74 65 00 70 61 64 00 73 70 61 77 6e 00 73 70 |ite.pad.spawn.sp| +0000e850 72 69 6e 74 00 63 76 74 68 65 78 00 63 76 74 75 |rint.cvthex.cvtu| +0000e860 6e 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 65 73 |ns0.kill.cwrites| +0000e870 00 65 78 65 63 00 77 61 69 74 00 73 77 72 69 74 |.exec.wait.swrit| +0000e880 65 73 00 5f 73 74 61 72 74 00 72 65 61 64 00 67 |es._start.read.g| +0000e890 65 74 70 72 69 6f 00 63 76 74 64 65 63 30 00 66 |etprio.cvtdec0.f| +0000e8a0 6f 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 69 64 |ork.main.getppid| +0000e8b0 00 70 61 64 73 74 72 00 73 65 74 70 72 69 6f 00 |.padstr.setprio.| +0000e8c0 63 76 74 6f 63 74 00 63 77 72 69 74 65 63 68 00 |cvtoct.cwritech.| +0000e8d0 67 65 74 74 69 6d 65 00 63 76 74 64 65 63 00 73 |gettime.cvtdec.s| +0000e8e0 74 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 6b 65 |trlen.bogus.fake| +0000e8f0 5f 65 78 69 74 00 00 2e 73 79 6d 74 61 62 00 2e |_exit...symtab..| +0000e900 73 74 72 74 61 62 00 2e 73 68 73 74 72 74 61 62 |strtab..shstrtab| +0000e910 00 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 00 2e |..text..rodata..| +0000e920 64 61 74 61 00 2e 62 73 73 00 00 00 00 00 00 00 |data..bss.......| +0000e930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +0000e950 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +0000e960 00 10 00 00 74 00 00 00 0d 0a 00 00 00 00 00 00 |....t...........| +0000e970 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +0000e980 01 00 00 00 02 00 00 00 10 1a 00 00 84 0a 00 00 |................| +0000e990 a4 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +0000e9a0 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +0000e9b0 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +0000e9c0 00 00 00 00 01 00 00 00 00 00 00 00 2f 00 00 00 |............/...| +0000e9d0 08 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +0000e9e0 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +0000e9f0 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +0000ea00 00 00 00 00 74 10 00 00 60 03 00 00 06 00 00 00 |....t...`.......| +0000ea10 12 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +0000ea20 03 00 00 00 00 00 00 00 00 00 00 00 d4 13 00 00 |................| +0000ea30 62 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |b...............| +0000ea40 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +0000ea50 00 00 00 00 36 15 00 00 34 00 00 00 00 00 00 00 |....6...4.......| +0000ea60 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +0000ea70 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +0000ea80 02 00 03 00 01 00 00 00 2a 14 00 00 34 00 00 00 |........*...4...| +0000ea90 6c 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |l.......4. ...(.| +0000eaa0 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +0000eab0 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +0000eac0 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +0000ead0 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +0000eae0 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +0000eaf0 e5 53 51 81 ec d0 00 00 00 89 cb c7 45 f4 05 00 |.SQ.........E...| +0000eb00 00 00 c6 45 e3 35 c7 45 f0 00 00 00 00 c7 45 de |...E.5.E......E.| +0000eb10 2a 35 77 2a c6 45 e2 00 c7 45 d9 2a 35 7a 2a c6 |*5w*.E...E.*5z*.| +0000eb20 45 dd 00 8b 03 83 f8 03 74 22 83 f8 04 74 07 83 |E.......t"...t..| +0000eb30 f8 02 74 31 eb 42 8b 43 04 83 c0 0c 8b 00 0f b6 |..t1.B.C........| +0000eb40 00 3c 74 0f 94 c0 0f b6 c0 89 45 f0 8b 43 04 83 |........'....E| +000102c0 e4 83 ec 04 ff 75 e4 68 00 1a 00 00 8d 85 63 ff |.....u.h......c.| +000102d0 ff ff 50 e8 53 02 00 00 83 c4 10 83 ec 0c 8d 85 |..P.S...........| +000102e0 63 ff ff ff 50 e8 73 01 00 00 83 c4 10 c7 45 e8 |c...P.s.......E.| +000102f0 00 00 00 00 eb 2c 8b 45 f0 69 c0 e8 03 00 00 83 |.....,.E.i......| +00010300 ec 0c 50 e8 fd 01 00 00 83 c4 10 83 ec 04 6a 01 |..P...........j.| +00010310 8d 45 e3 50 6a 01 e8 b2 01 00 00 83 c4 10 83 45 |.E.Pj..........E| +00010320 e8 01 8b 45 e8 3b 45 f4 7c cc 83 ec 0c 6a 00 e8 |...E.;E.|....j..| +00010330 71 01 00 00 83 c4 10 b8 2a 00 00 00 8d 65 f8 59 |q.......*....e.Y| +00010340 5b 5d 8d 61 fc c3 55 89 e5 83 ec 08 83 ec 08 ff |[].a..U.........| +00010350 75 08 6a 00 e8 54 01 00 00 83 c4 10 c9 c3 55 89 |u.j..T........U.| +00010360 e5 81 ec 18 01 00 00 e8 49 01 00 00 89 45 f4 83 |........I....E..| +00010370 7d f4 00 74 05 8b 45 f4 eb 57 e8 56 01 00 00 89 |}..t..E..W.V....| +00010380 45 f4 83 ec 08 ff 75 0c ff 75 08 e8 2d 01 00 00 |E.....u..u..-...| +00010390 83 c4 10 ff 75 08 ff 75 f4 68 06 1a 00 00 8d 85 |....u..u.h......| +000103a0 f4 fe ff ff 50 e8 81 01 00 00 83 c4 10 83 ec 0c |....P...........| +000103b0 8d 85 f4 fe ff ff 50 e8 38 00 00 00 83 c4 10 83 |......P.8.......| +000103c0 ec 0c 6a ff e8 dc 00 00 00 83 c4 10 b8 00 00 00 |..j.............| +000103d0 00 c9 c3 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 |...U......E..E..| +000103e0 ec 04 6a 01 8d 45 f4 50 6a 00 e8 de 00 00 00 83 |..j..E.Pj.......| +000103f0 c4 10 c9 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 |....U.........u.| +00010400 e8 0d 04 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec |.........E..E...| +00010410 04 50 ff 75 08 6a 00 e8 b1 00 00 00 83 c4 10 c9 |.P.u.j..........| +00010420 c3 55 89 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 |.U.........u..u.| +00010430 6a 00 e8 96 00 00 00 83 c4 10 c9 c3 55 89 e5 83 |j...........U...| +00010440 ec 18 8b 45 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 |...E..E....j..E.| +00010450 50 6a 01 e8 75 00 00 00 83 c4 10 c9 c3 55 89 e5 |Pj..u........U..| +00010460 83 ec 18 83 ec 0c ff 75 08 e8 a4 03 00 00 83 c4 |.......u........| +00010470 10 89 45 f4 8b 45 f4 83 ec 04 50 ff 75 08 6a 01 |..E..E....P.u.j.| +00010480 e8 48 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 |.H........U.....| +00010490 83 ec 04 ff 75 0c ff 75 08 6a 01 e8 2d 00 00 00 |....u..u.j..-...| +000104a0 83 c4 10 c9 c3 b8 00 00 00 00 cd 80 c3 b8 01 00 |................| +000104b0 00 00 cd 80 c3 b8 02 00 00 00 cd 80 c3 b8 03 00 |................| +000104c0 00 00 cd 80 c3 b8 04 00 00 00 cd 80 c3 b8 05 00 |................| +000104d0 00 00 cd 80 c3 b8 06 00 00 00 cd 80 c3 b8 07 00 |................| +000104e0 00 00 cd 80 c3 b8 08 00 00 00 cd 80 c3 b8 09 00 |................| +000104f0 00 00 cd 80 c3 b8 0a 00 00 00 cd 80 c3 b8 0b 00 |................| +00010500 00 00 cd 80 c3 b8 0c 00 00 00 cd 80 c3 b8 ad 0b |................| +00010510 00 00 cd 80 c3 50 e8 8a ff ff ff e8 74 fc ff ff |.....P......t...| +00010520 83 ec 0c 50 e8 7c ff ff ff eb fe 55 89 e5 83 ec |...P.|.....U....| +00010530 38 8d 45 0c 83 c0 04 89 45 f4 e9 3f 02 00 00 80 |8.E.....E..?....| +00010540 7d f3 25 0f 85 26 02 00 00 c7 45 ec 00 00 00 00 |}.%..&....E.....| +00010550 c7 45 e4 20 00 00 00 c7 45 e8 00 00 00 00 8b 45 |.E. ....E......E| +00010560 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 |..P..U.....E..}.| +00010570 2d 75 16 c7 45 ec 01 00 00 00 8b 45 0c 8d 50 01 |-u..E......E..P.| +00010580 89 55 0c 0f b6 00 88 45 f3 80 7d f3 30 75 40 c7 |.U.....E..}.0u@.| +00010590 45 e4 30 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f |E.0....E..P..U..| +000105a0 b6 00 88 45 f3 eb 28 8b 55 e8 89 d0 c1 e0 02 01 |...E..(.U.......| +000105b0 d0 01 c0 89 45 e8 0f be 45 f3 83 e8 30 01 45 e8 |....E...E...0.E.| +000105c0 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 |.E..P..U.....E..| +000105d0 7d f3 2f 7e 06 80 7d f3 39 7e cc 0f be 45 f3 83 |}./~..}.9~...E..| +000105e0 e8 63 83 f8 15 0f 87 93 01 00 00 8b 04 85 24 1a |.c............$.| +000105f0 00 00 ff e0 8b 45 f4 8d 50 04 89 55 f4 8b 00 88 |.....E..P..U....| +00010600 45 f3 0f b6 45 f3 88 45 d0 c6 45 d1 00 83 ec 08 |E...E..E..E.....| +00010610 ff 75 e4 ff 75 ec ff 75 e8 6a 01 8d 45 d0 50 ff |.u..u..u.j..E.P.| +00010620 75 08 e8 89 04 00 00 83 c4 20 89 45 08 e9 4c 01 |u........ .E..L.| +00010630 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 |...E..P..U......| +00010640 50 8d 45 d0 50 e8 ea 01 00 00 83 c4 10 89 45 e0 |P.E.P.........E.| +00010650 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d |....u..u..u..u..| +00010660 45 d0 50 ff 75 08 e8 45 04 00 00 83 c4 20 89 45 |E.P.u..E..... .E| +00010670 08 e9 08 01 00 00 8b 45 f4 8d 50 04 89 55 f4 8b |.......E..P..U..| +00010680 00 89 45 dc 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 |..E.....u..u..u.| +00010690 6a ff ff 75 dc ff 75 08 e8 13 04 00 00 83 c4 20 |j..u..u........ | +000106a0 89 45 08 e9 d6 00 00 00 8b 45 f4 8d 50 04 89 55 |.E.......E..P..U| +000106b0 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 44 02 00 00 |......P.E.P.D...| +000106c0 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff |....E.....u..u..| +000106d0 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 cf 03 00 |u..u..E.P.u.....| +000106e0 00 83 c4 20 89 45 08 e9 92 00 00 00 8b 45 f4 8d |... .E.......E..| +000106f0 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 |P..U......P.E.P.| +00010700 8a 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 |........E.....u.| +00010710 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 |.u..u..u..E.P.u.| +00010720 e8 8b 03 00 00 83 c4 20 89 45 08 eb 51 8b 45 f4 |....... .E..Q.E.| +00010730 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 |.P..U......P.E.P| +00010740 e8 d3 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 |.........E.....u| +00010750 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 |..u..u..u..E.P.u| +00010760 08 e8 4a 03 00 00 83 c4 20 89 45 08 90 eb 0f 8b |..J..... .E.....| +00010770 45 08 8d 50 01 89 55 08 0f b6 55 f3 88 10 8b 45 |E..P..U...U....E| +00010780 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 |..P..U.....E..}.| +00010790 00 0f 85 a8 fd ff ff 8b 45 08 c6 00 00 90 c9 c3 |........E.......| +000107a0 55 89 e5 53 83 ec 14 8b 45 08 8b 4d 0c bb 00 00 |U..S....E..M....| +000107b0 00 00 c6 45 eb 39 c7 45 f8 01 00 00 00 0f b6 10 |...E.9.E........| +000107c0 80 fa 2d 75 0a c7 45 f8 ff ff ff ff 83 c0 01 83 |..-u..E.........| +000107d0 f9 0a 74 2b 89 ca 83 c2 2f 88 55 eb eb 21 0f b6 |..t+..../.U..!..| +000107e0 10 80 fa 2f 7e 20 0f b6 10 38 55 eb 7c 18 0f af |.../~ ...8U.|...| +000107f0 d9 0f b6 10 0f be d2 01 da 8d 5a d0 83 c0 01 0f |..........Z.....| +00010800 b6 10 84 d2 75 d8 89 d8 0f af 45 f8 83 c4 14 5b |....u.....E....[| +00010810 5d c3 55 89 e5 53 8b 55 08 bb 00 00 00 00 eb 03 |].U..S.U........| +00010820 83 c3 01 89 d0 8d 50 01 0f b6 00 84 c0 75 f1 89 |......P......u..| +00010830 d8 5b 5d c3 55 89 e5 83 ec 18 8b 45 08 89 45 f4 |.[].U......E..E.| +00010840 83 7d 0c 00 79 0f 8b 45 f4 8d 50 01 89 55 f4 c6 |.}..y..E..P..U..| +00010850 00 2d f7 5d 0c 83 ec 08 ff 75 0c ff 75 f4 e8 18 |.-.].....u..u...| +00010860 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 00 00 8b |.......E..E.....| +00010870 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec |U..E.).....U....| +00010880 18 8b 4d 0c ba 67 66 66 66 89 c8 f7 ea c1 fa 02 |..M..gfff.......| +00010890 89 c8 c1 f8 1f 29 c2 89 d0 89 45 f4 83 7d f4 00 |.....)....E..}..| +000108a0 79 0e c7 45 f4 cc cc cc 0c c7 45 0c 08 00 00 00 |y..E......E.....| +000108b0 83 7d f4 00 74 14 83 ec 08 ff 75 f4 ff 75 08 e8 |.}..t.....u..u..| +000108c0 b7 ff ff ff 83 c4 10 89 45 08 8b 4d 0c ba 67 66 |........E..M..gf| +000108d0 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 |ff............).| +000108e0 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d |.........)......| +000108f0 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 8b |H0.E..P..U......| +00010900 45 08 c9 c3 55 89 e5 83 ec 20 c7 45 e3 30 31 32 |E...U.... .E.012| +00010910 33 c7 45 e7 34 35 36 37 c7 45 eb 38 39 41 42 c7 |3.E.4567.E.89AB.| +00010920 45 ef 43 44 45 46 c6 45 f3 00 c7 45 fc 00 00 00 |E.CDEF.E...E....| +00010930 00 c7 45 f8 00 00 00 00 eb 43 8b 45 0c 25 00 00 |..E......C.E.%..| +00010940 00 f0 89 45 f4 83 7d fc 00 75 0c 83 7d f4 00 75 |...E..}..u..}..u| +00010950 06 83 7d f8 07 75 1e 83 45 fc 01 c1 6d f4 1c 8b |..}..u..E...m...| +00010960 45 08 8d 50 01 89 55 08 8d 4d e3 8b 55 f4 01 ca |E..P..U..M..U...| +00010970 0f b6 12 88 10 c1 65 0c 04 83 45 f8 01 83 7d f8 |......e...E...}.| +00010980 07 7e b7 8b 45 08 c6 00 00 8b 45 fc c9 c3 55 89 |.~..E.....E...U.| +00010990 e5 83 ec 10 c7 45 f8 00 00 00 00 8b 45 08 89 45 |.....E......E..E| +000109a0 f4 8b 45 0c 25 00 00 00 c0 89 45 f0 c1 6d f0 1e |..E.%.....E..m..| +000109b0 c7 45 fc 00 00 00 00 eb 47 83 7d fc 0a 74 0c 83 |.E......G.}..t..| +000109c0 7d f0 00 75 06 83 7d f8 00 74 1e c7 45 f8 01 00 |}..u..}..t..E...| +000109d0 00 00 83 65 f0 07 8b 45 f0 8d 48 30 8b 45 f4 8d |...e...E..H0.E..| +000109e0 50 01 89 55 f4 89 ca 88 10 c1 65 0c 03 8b 45 0c |P..U......e...E.| +000109f0 25 00 00 00 e0 89 45 f0 c1 6d f0 1d 83 45 fc 01 |%.....E..m...E..| +00010a00 83 7d fc 0a 7e b3 8b 45 f4 c6 00 00 8b 55 f4 8b |.}..~..E.....U..| +00010a10 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b 45 |E.).....U......E| +00010a20 08 89 45 f4 83 ec 08 ff 75 0c ff 75 f4 e8 18 00 |..E.....u..u....| +00010a30 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 00 00 8b 55 |......E..E.....U| +00010a40 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 ec 18 |..E.).....U.....| +00010a50 8b 45 0c ba cd cc cc cc f7 e2 89 d0 c1 e8 03 89 |.E..............| +00010a60 45 f4 83 7d f4 00 74 15 8b 45 f4 83 ec 08 50 ff |E..}..t..E....P.| +00010a70 75 08 e8 04 fe ff ff 83 c4 10 89 45 08 8b 4d 0c |u..........E..M.| +00010a80 ba cd cc cc cc 89 c8 f7 e2 c1 ea 03 89 d0 c1 e0 |................| +00010a90 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d 48 30 8b 45 |.....)......H0.E| +00010aa0 08 8d 50 01 89 55 08 89 ca 88 10 8b 45 08 c9 c3 |..P..U......E...| +00010ab0 55 89 e5 83 ec 18 83 7d 10 00 79 11 83 ec 0c ff |U......}..y.....| +00010ac0 75 0c e8 4b fd ff ff 83 c4 10 89 45 10 8b 45 14 |u..K.......E..E.| +00010ad0 2b 45 10 89 45 f0 83 7d f0 00 7e 1d 83 7d 18 00 |+E..E..}..~..}..| +00010ae0 75 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 08 e8 5a |u.....u..u..u..Z| +00010af0 00 00 00 83 c4 10 89 45 08 c7 45 f4 00 00 00 00 |.......E..E.....| +00010b00 eb 1b 8b 55 f4 8b 45 0c 8d 0c 02 8b 45 08 8d 50 |...U..E.....E..P| +00010b10 01 89 55 08 0f b6 11 88 10 83 45 f4 01 8b 45 f4 |..U.......E...E.| +00010b20 3b 45 10 7c dd 83 7d f0 00 7e 1d 83 7d 18 00 74 |;E.|..}..~..}..t| +00010b30 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 08 e8 0b 00 |.....u..u..u....| +00010b40 00 00 83 c4 10 89 45 08 8b 45 08 c9 c3 55 89 e5 |......E..E...U..| +00010b50 eb 12 8b 45 08 8d 50 01 89 55 08 8b 55 10 88 10 |...E..P..U..U...| +00010b60 83 6d 0c 01 83 7d 0c 00 7f e8 8b 45 08 5d c3 00 |.m...}.....E.]..| +00010b70 75 73 65 72 50 3a 20 61 72 67 63 20 25 64 2c 20 |userP: argc %d, | +00010b80 61 72 67 73 3a 20 00 28 6e 75 6c 6c 29 00 20 25 |args: .(null). %| +00010b90 73 00 0a 00 20 50 40 25 75 00 43 68 69 6c 64 20 |s... P@%u.Child | +00010ba0 25 64 20 65 78 65 63 28 29 20 23 25 75 20 66 61 |%d exec() #%u fa| +00010bb0 69 6c 65 64 0a 00 00 00 60 14 00 00 9e 14 00 00 |iled....`.......| +00010bc0 ea 15 00 00 ea 15 00 00 ea 15 00 00 ea 15 00 00 |................| +* +00010be0 ea 15 00 00 ea 15 00 00 58 15 00 00 ea 15 00 00 |........X.......| +00010bf0 ea 15 00 00 ea 15 00 00 e2 14 00 00 ea 15 00 00 |................| +00010c00 99 15 00 00 ea 15 00 00 ea 15 00 00 14 15 00 00 |................| +00010c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +000111a0 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +000111b0 03 00 01 00 00 00 00 00 dc 19 00 00 00 00 00 00 |................| +000111c0 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +000111d0 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +000111e0 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +000111f0 04 00 f1 ff 09 00 00 00 00 00 00 00 00 00 00 00 |................| +00011200 04 00 f1 ff 11 00 00 00 00 00 00 00 00 00 00 00 |................| +00011210 04 00 f1 ff 1a 00 00 00 00 00 00 00 00 00 00 00 |................| +00011220 04 00 f1 ff 24 00 00 00 00 00 00 00 00 00 00 00 |....$...........| +00011230 04 00 f1 ff 2d 00 00 00 00 00 00 00 00 00 00 00 |....-...........| +00011240 04 00 f1 ff 36 00 00 00 00 00 00 00 00 00 00 00 |....6...........| +00011250 04 00 f1 ff 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00011260 04 00 f1 ff 49 00 00 00 00 00 00 00 00 00 00 00 |....I...........| +00011270 04 00 f1 ff 52 00 00 00 00 00 00 00 00 00 00 00 |....R...........| +00011280 04 00 f1 ff 5b 00 00 00 00 00 00 00 00 00 00 00 |....[...........| +00011290 04 00 f1 ff 65 00 00 00 00 00 00 00 00 00 00 00 |....e...........| +000112a0 04 00 f1 ff 6e 00 00 00 00 00 00 00 00 00 00 00 |....n...........| +000112b0 04 00 f1 ff 74 00 00 00 a8 12 00 00 21 00 00 00 |....t.......!...| +000112c0 12 00 01 00 7d 00 00 00 19 13 00 00 00 00 00 00 |....}...........| +000112d0 10 00 01 00 85 00 00 00 8d 12 00 00 1b 00 00 00 |................| +000112e0 12 00 01 00 8c 00 00 00 0c 16 00 00 72 00 00 00 |............r...| +000112f0 12 00 01 00 94 00 00 00 84 18 00 00 32 00 00 00 |............2...| +00011300 12 00 01 00 9b 00 00 00 41 13 00 00 00 00 00 00 |........A.......| +00011310 10 00 01 00 a2 00 00 00 71 13 00 00 00 00 00 00 |........q.......| +00011320 10 00 01 00 a8 00 00 00 f6 12 00 00 1b 00 00 00 |................| +00011330 12 00 01 00 af 00 00 00 b9 19 00 00 22 00 00 00 |............"...| +00011340 12 00 01 00 b3 00 00 00 ca 11 00 00 75 00 00 00 |............u...| +00011350 12 00 01 00 b9 00 00 00 97 13 00 00 75 02 00 00 |............u...| +00011360 12 00 01 00 c0 00 00 00 70 17 00 00 8a 00 00 00 |........p.......| +00011370 12 00 01 00 c7 00 00 00 b6 18 00 00 66 00 00 00 |............f...| +00011380 12 00 01 00 86 00 00 00 39 13 00 00 00 00 00 00 |........9.......| +00011390 10 00 01 00 cf 00 00 00 69 13 00 00 00 00 00 00 |........i.......| +000113a0 10 00 01 00 d4 00 00 00 60 12 00 00 2d 00 00 00 |........`...-...| +000113b0 12 00 01 00 dc 00 00 00 29 13 00 00 00 00 00 00 |........).......| +000113c0 10 00 01 00 e1 00 00 00 b2 11 00 00 18 00 00 00 |................| +000113d0 12 00 01 00 e6 00 00 00 c9 12 00 00 2d 00 00 00 |............-...| +000113e0 12 00 01 00 ee 00 00 00 87 13 00 00 00 00 00 00 |................| +000113f0 10 00 01 00 f5 00 00 00 31 13 00 00 00 00 00 00 |........1.......| +00011400 10 00 01 00 fa 00 00 00 59 13 00 00 00 00 00 00 |........Y.......| +00011410 10 00 01 00 02 01 00 00 e7 16 00 00 89 00 00 00 |................| +00011420 12 00 01 00 0a 01 00 00 21 13 00 00 00 00 00 00 |........!.......| +00011430 10 00 01 00 0f 01 00 00 00 10 00 00 b2 01 00 00 |................| +00011440 12 00 01 00 14 01 00 00 49 13 00 00 00 00 00 00 |........I.......| +00011450 10 00 01 00 1c 01 00 00 1c 19 00 00 9d 00 00 00 |................| +00011460 12 00 01 00 23 01 00 00 61 13 00 00 00 00 00 00 |....#...a.......| +00011470 10 00 01 00 2b 01 00 00 fa 17 00 00 8a 00 00 00 |....+...........| +00011480 12 00 01 00 32 01 00 00 3f 12 00 00 21 00 00 00 |....2...?...!...| +00011490 12 00 01 00 3b 01 00 00 51 13 00 00 00 00 00 00 |....;...Q.......| +000114a0 10 00 01 00 43 01 00 00 a0 16 00 00 47 00 00 00 |....C.......G...| +000114b0 12 00 01 00 5c 01 00 00 11 13 00 00 00 00 00 00 |....\...........| +000114c0 10 00 01 00 4a 01 00 00 7e 16 00 00 22 00 00 00 |....J...~..."...| +000114d0 12 00 01 00 51 01 00 00 79 13 00 00 00 00 00 00 |....Q...y.......| +000114e0 10 00 01 00 57 01 00 00 81 13 00 00 00 00 00 00 |....W...........| +000114f0 10 00 01 00 00 70 72 6f 67 50 2e 63 00 75 6c 69 |.....progP.c.uli| +00011500 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 74 |bc.c.sprint.c.st| +00011510 72 32 69 6e 74 2e 63 00 73 74 72 6c 65 6e 2e 63 |r2int.c.strlen.c| +00011520 00 63 76 74 64 65 63 2e 63 00 63 76 74 64 65 63 |.cvtdec.c.cvtdec| +00011530 30 2e 63 00 63 76 74 68 65 78 2e 63 00 63 76 74 |0.c.cvthex.c.cvt| +00011540 6f 63 74 2e 63 00 63 76 74 75 6e 73 2e 63 00 63 |oct.c.cvtuns.c.c| +00011550 76 74 75 6e 73 30 2e 63 00 70 61 64 73 74 72 2e |vtuns0.c.padstr.| +00011560 63 00 70 61 64 2e 63 00 73 77 72 69 74 65 63 68 |c.pad.c.swritech| +00011570 00 77 61 69 74 70 69 64 00 63 77 72 69 74 65 00 |.waitpid.cwrite.| +00011580 73 74 72 32 69 6e 74 00 63 76 74 75 6e 73 00 67 |str2int.cvtuns.g| +00011590 65 74 70 69 64 00 73 6c 65 65 70 00 73 77 72 69 |etpid.sleep.swri| +000115a0 74 65 00 70 61 64 00 73 70 61 77 6e 00 73 70 72 |te.pad.spawn.spr| +000115b0 69 6e 74 00 63 76 74 68 65 78 00 63 76 74 75 6e |int.cvthex.cvtun| +000115c0 73 30 00 6b 69 6c 6c 00 63 77 72 69 74 65 73 00 |s0.kill.cwrites.| +000115d0 65 78 65 63 00 77 61 69 74 00 73 77 72 69 74 65 |exec.wait.swrite| +000115e0 73 00 5f 73 74 61 72 74 00 72 65 61 64 00 67 65 |s._start.read.ge| +000115f0 74 70 72 69 6f 00 63 76 74 64 65 63 30 00 66 6f |tprio.cvtdec0.fo| +00011600 72 6b 00 6d 61 69 6e 00 67 65 74 70 70 69 64 00 |rk.main.getppid.| +00011610 70 61 64 73 74 72 00 73 65 74 70 72 69 6f 00 63 |padstr.setprio.c| +00011620 76 74 6f 63 74 00 63 77 72 69 74 65 63 68 00 67 |vtoct.cwritech.g| +00011630 65 74 74 69 6d 65 00 63 76 74 64 65 63 00 73 74 |ettime.cvtdec.st| +00011640 72 6c 65 6e 00 62 6f 67 75 73 00 66 61 6b 65 5f |rlen.bogus.fake_| +00011650 65 78 69 74 00 00 2e 73 79 6d 74 61 62 00 2e 73 |exit...symtab..s| +00011660 74 72 74 61 62 00 2e 73 68 73 74 72 74 61 62 00 |trtab..shstrtab.| +00011670 2e 74 65 78 74 00 2e 72 6f 64 61 74 61 00 2e 64 |.text..rodata..d| +00011680 61 74 61 00 2e 62 73 73 00 00 00 00 00 00 00 00 |ata..bss........| +00011690 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +000116b0 00 00 00 00 1b 00 00 00 01 00 00 00 06 00 00 00 |................| +000116c0 00 10 00 00 74 00 00 00 db 09 00 00 00 00 00 00 |....t...........| +000116d0 00 00 00 00 01 00 00 00 00 00 00 00 21 00 00 00 |............!...| +000116e0 01 00 00 00 02 00 00 00 dc 19 00 00 50 0a 00 00 |............P...| +000116f0 a0 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| +00011700 00 00 00 00 29 00 00 00 01 00 00 00 03 00 00 00 |....)...........| +00011710 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +00011720 00 00 00 00 01 00 00 00 00 00 00 00 2f 00 00 00 |............/...| +00011730 08 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +00011740 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +00011750 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 |................| +00011760 00 00 00 00 74 10 00 00 60 03 00 00 06 00 00 00 |....t...`.......| +00011770 12 00 00 00 04 00 00 00 10 00 00 00 09 00 00 00 |................| +00011780 03 00 00 00 00 00 00 00 00 00 00 00 d4 13 00 00 |................| +00011790 61 01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |a...............| +000117a0 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| +000117b0 00 00 00 00 35 15 00 00 34 00 00 00 00 00 00 00 |....5...4.......| +000117c0 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +000117d0 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| +000117e0 02 00 03 00 01 00 00 00 13 13 00 00 34 00 00 00 |............4...| +000117f0 38 15 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |8.......4. ...(.| +00011800 08 00 07 00 01 00 00 00 74 00 00 00 00 10 00 00 |........t.......| +00011810 00 10 00 00 00 10 00 00 00 10 00 00 07 00 00 00 |................| +00011820 04 00 00 00 51 e5 74 64 00 00 00 00 00 00 00 00 |....Q.td........| +00011830 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................| +00011840 10 00 00 00 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 |.....L$.....q.U.| +00011850 e5 53 51 81 ec 90 00 00 00 89 cb c6 45 f3 71 8b |.SQ.........E.q.| +00011860 03 83 f8 02 75 13 8b 43 04 83 c0 04 8b 00 0f b6 |....u..C........| +00011870 00 88 45 f3 e9 a4 00 00 00 83 ec 04 ff 33 68 f8 |..E..........3h.| +00011880 18 00 00 8d 85 73 ff ff ff 50 e8 d8 02 00 00 83 |.....s...P......| +00011890 c4 10 83 ec 0c 8d 85 73 ff ff ff 50 e8 8f 01 00 |.......s...P....| +000118a0 00 83 c4 10 c7 45 f4 00 00 00 00 eb 59 8b 03 8d |.....E......Y...| +000118b0 14 85 00 00 00 00 8b 43 04 01 d0 8b 00 85 c0 74 |.......C.......t| +000118c0 12 8b 03 8d 14 85 00 00 00 00 8b 43 04 01 d0 8b |...........C....| +000118d0 00 eb 05 b8 0f 19 00 00 83 ec 04 50 68 16 19 00 |...........Ph...| +000118e0 00 8d 85 73 ff ff ff 50 e8 7a 02 00 00 83 c4 10 |...s...P.z......| +000118f0 83 ec 0c 8d 85 73 ff ff ff 50 e8 31 01 00 00 83 |.....s...P.1....| +00011900 c4 10 83 45 f4 01 8b 45 f4 3b 03 7e a0 83 ec 0c |...E...E.;.~....| +00011910 68 1a 19 00 00 e8 16 01 00 00 83 c4 10 83 ec 04 |h...............| +00011920 6a 01 8d 45 f3 50 6a 01 e8 dc 01 00 00 83 c4 10 |j..E.Pj.........| +00011930 e8 14 02 00 00 0f b6 45 f3 0f be c0 83 ec 04 50 |.......E.......P| +00011940 68 1c 19 00 00 8d 85 73 ff ff ff 50 e8 16 02 00 |h......s...P....| +00011950 00 83 c4 10 83 ec 0c 8d 85 73 ff ff ff 50 e8 cd |.........s...P..| +00011960 00 00 00 83 c4 10 83 ec 0c 6a 01 e8 71 01 00 00 |.........j..q...| +00011970 83 c4 10 b8 2a 00 00 00 8d 65 f8 59 5b 5d 8d 61 |....*....e.Y[].a| +00011980 fc c3 55 89 e5 83 ec 08 83 ec 08 ff 75 08 6a 00 |..U.........u.j.| +00011990 e8 54 01 00 00 83 c4 10 c9 c3 55 89 e5 81 ec 18 |.T........U.....| +000119a0 01 00 00 e8 49 01 00 00 89 45 f4 83 7d f4 00 74 |....I....E..}..t| +000119b0 05 8b 45 f4 eb 57 e8 56 01 00 00 89 45 f4 83 ec |..E..W.V....E...| +000119c0 08 ff 75 0c ff 75 08 e8 2d 01 00 00 83 c4 10 ff |..u..u..-.......| +000119d0 75 08 ff 75 f4 68 47 19 00 00 8d 85 f4 fe ff ff |u..u.hG.........| +000119e0 50 e8 81 01 00 00 83 c4 10 83 ec 0c 8d 85 f4 fe |P...............| +000119f0 ff ff 50 e8 38 00 00 00 83 c4 10 83 ec 0c 6a ff |..P.8.........j.| +00011a00 e8 dc 00 00 00 83 c4 10 b8 00 00 00 00 c9 c3 55 |...............U| +00011a10 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 6a 01 |......E..E....j.| +00011a20 8d 45 f4 50 6a 00 e8 de 00 00 00 83 c4 10 c9 c3 |.E.Pj...........| +00011a30 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 9b 03 00 |U.........u.....| +00011a40 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 ff 75 |.....E..E....P.u| +00011a50 08 6a 00 e8 b1 00 00 00 83 c4 10 c9 c3 55 89 e5 |.j...........U..| +00011a60 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 00 e8 96 |.......u..u.j...| +00011a70 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 8b 45 |........U......E| +00011a80 08 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 01 e8 |..E....j..E.Pj..| +00011a90 75 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 |u........U......| +00011aa0 ec 0c ff 75 08 e8 32 03 00 00 83 c4 10 89 45 f4 |...u..2.......E.| +00011ab0 8b 45 f4 83 ec 04 50 ff 75 08 6a 01 e8 48 00 00 |.E....P.u.j..H..| +00011ac0 00 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff |......U.........| +00011ad0 75 0c ff 75 08 6a 01 e8 2d 00 00 00 83 c4 10 c9 |u..u.j..-.......| +00011ae0 c3 b8 00 00 00 00 cd 80 c3 b8 01 00 00 00 cd 80 |................| +00011af0 c3 b8 02 00 00 00 cd 80 c3 b8 03 00 00 00 cd 80 |................| +00011b00 c3 b8 04 00 00 00 cd 80 c3 b8 05 00 00 00 cd 80 |................| +00011b10 c3 b8 06 00 00 00 cd 80 c3 b8 07 00 00 00 cd 80 |................| +00011b20 c3 b8 08 00 00 00 cd 80 c3 b8 09 00 00 00 cd 80 |................| +00011b30 c3 b8 0a 00 00 00 cd 80 c3 b8 0b 00 00 00 cd 80 |................| +00011b40 c3 b8 0c 00 00 00 cd 80 c3 b8 ad 0b 00 00 cd 80 |................| +00011b50 c3 50 e8 8a ff ff ff e8 e8 fc ff ff 83 ec 0c 50 |.P.............P| +00011b60 e8 7c ff ff ff eb fe 55 89 e5 83 ec 38 8d 45 0c |.|.....U....8.E.| +00011b70 83 c0 04 89 45 f4 e9 3f 02 00 00 80 7d f3 25 0f |....E..?....}.%.| +00011b80 85 26 02 00 00 c7 45 ec 00 00 00 00 c7 45 e4 20 |.&....E......E. | +00011b90 00 00 00 c7 45 e8 00 00 00 00 8b 45 0c 8d 50 01 |....E......E..P.| +00011ba0 89 55 0c 0f b6 00 88 45 f3 80 7d f3 2d 75 16 c7 |.U.....E..}.-u..| +00011bb0 45 ec 01 00 00 00 8b 45 0c 8d 50 01 89 55 0c 0f |E......E..P..U..| +00011bc0 b6 00 88 45 f3 80 7d f3 30 75 40 c7 45 e4 30 00 |...E..}.0u@.E.0.| +00011bd0 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +00011be0 f3 eb 28 8b 55 e8 89 d0 c1 e0 02 01 d0 01 c0 89 |..(.U...........| +00011bf0 45 e8 0f be 45 f3 83 e8 30 01 45 e8 8b 45 0c 8d |E...E...0.E..E..| +00011c00 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 2f 7e |P..U.....E..}./~| +00011c10 06 80 7d f3 39 7e cc 0f be 45 f3 83 e8 63 83 f8 |..}.9~...E...c..| +00011c20 15 0f 87 93 01 00 00 8b 04 85 64 19 00 00 ff e0 |..........d.....| +00011c30 8b 45 f4 8d 50 04 89 55 f4 8b 00 88 45 f3 0f b6 |.E..P..U....E...| +00011c40 45 f3 88 45 d0 c6 45 d1 00 83 ec 08 ff 75 e4 ff |E..E..E......u..| +00011c50 75 ec ff 75 e8 6a 01 8d 45 d0 50 ff 75 08 e8 17 |u..u.j..E.P.u...| +00011c60 04 00 00 83 c4 20 89 45 08 e9 4c 01 00 00 8b 45 |..... .E..L....E| +00011c70 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 |..P..U......P.E.| +00011c80 50 e8 78 01 00 00 83 c4 10 89 45 e0 83 ec 08 ff |P.x.......E.....| +00011c90 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff |u..u..u..u..E.P.| +00011ca0 75 08 e8 d3 03 00 00 83 c4 20 89 45 08 e9 08 01 |u........ .E....| +00011cb0 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 89 45 dc |...E..P..U....E.| +00011cc0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a ff ff 75 |....u..u..u.j..u| +00011cd0 dc ff 75 08 e8 a1 03 00 00 83 c4 20 89 45 08 e9 |..u........ .E..| +00011ce0 d6 00 00 00 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 |.....E..P..U....| +00011cf0 ec 08 50 8d 45 d0 50 e8 d2 01 00 00 83 c4 10 89 |..P.E.P.........| +00011d00 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 |E.....u..u..u..u| +00011d10 e0 8d 45 d0 50 ff 75 08 e8 5d 03 00 00 83 c4 20 |..E.P.u..]..... | +00011d20 89 45 08 e9 92 00 00 00 8b 45 f4 8d 50 04 89 55 |.E.......E..P..U| +00011d30 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 18 02 00 00 |......P.E.P.....| +00011d40 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff |....E.....u..u..| +00011d50 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 19 03 00 |u..u..E.P.u.....| +00011d60 00 83 c4 20 89 45 08 eb 51 8b 45 f4 8d 50 04 89 |... .E..Q.E..P..| +00011d70 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 61 02 00 |U......P.E.P.a..| +00011d80 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec |.....E.....u..u.| +00011d90 ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 e8 d8 02 |.u..u..E.P.u....| +00011da0 00 00 83 c4 20 89 45 08 90 eb 0f 8b 45 08 8d 50 |.... .E.....E..P| +00011db0 01 89 55 08 0f b6 55 f3 88 10 8b 45 0c 8d 50 01 |..U...U....E..P.| +00011dc0 89 55 0c 0f b6 00 88 45 f3 80 7d f3 00 0f 85 a8 |.U.....E..}.....| +00011dd0 fd ff ff 8b 45 08 c6 00 00 90 c9 c3 55 89 e5 53 |....E.......U..S| +00011de0 8b 55 08 bb 00 00 00 00 eb 03 83 c3 01 89 d0 8d |.U..............| +00011df0 50 01 0f b6 00 84 c0 75 f1 89 d8 5b 5d c3 55 89 |P......u...[].U.| +00011e00 e5 83 ec 18 8b 45 08 89 45 f4 83 7d 0c 00 79 0f |.....E..E..}..y.| +00011e10 8b 45 f4 8d 50 01 89 55 f4 c6 00 2d f7 5d 0c 83 |.E..P..U...-.]..| +00011e20 ec 08 ff 75 0c ff 75 f4 e8 18 00 00 00 83 c4 10 |...u..u.........| +00011e30 89 45 f4 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 |.E..E.....U..E.)| +00011e40 c2 89 d0 c9 c3 55 89 e5 83 ec 18 8b 4d 0c ba 67 |.....U......M..g| +00011e50 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 f8 1f 29 |fff............)| +00011e60 c2 89 d0 89 45 f4 83 7d f4 00 79 0e c7 45 f4 cc |....E..}..y..E..| +00011e70 cc cc 0c c7 45 0c 08 00 00 00 83 7d f4 00 74 14 |....E......}..t.| +00011e80 83 ec 08 ff 75 f4 ff 75 08 e8 b7 ff ff ff 83 c4 |....u..u........| +00011e90 10 89 45 08 8b 4d 0c ba 67 66 66 66 89 c8 f7 ea |..E..M..gfff....| +00011ea0 c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 c1 e0 02 01 |........).......| +00011eb0 d0 01 c0 29 c1 89 ca 89 d0 8d 48 30 8b 45 08 8d |...)......H0.E..| +00011ec0 50 01 89 55 08 89 ca 88 10 8b 45 08 c9 c3 55 89 |P..U......E...U.| +00011ed0 e5 83 ec 20 c7 45 e3 30 31 32 33 c7 45 e7 34 35 |... .E.0123.E.45| +00011ee0 36 37 c7 45 eb 38 39 41 42 c7 45 ef 43 44 45 46 |67.E.89AB.E.CDEF| +00011ef0 c6 45 f3 00 c7 45 fc 00 00 00 00 c7 45 f8 00 00 |.E...E......E...| +00011f00 00 00 eb 43 8b 45 0c 25 00 00 00 f0 89 45 f4 83 |...C.E.%.....E..| +00011f10 7d fc 00 75 0c 83 7d f4 00 75 06 83 7d f8 07 75 |}..u..}..u..}..u| +00011f20 1e 83 45 fc 01 c1 6d f4 1c 8b 45 08 8d 50 01 89 |..E...m...E..P..| +00011f30 55 08 8d 4d e3 8b 55 f4 01 ca 0f b6 12 88 10 c1 |U..M..U.........| +00011f40 65 0c 04 83 45 f8 01 83 7d f8 07 7e b7 8b 45 08 |e...E...}..~..E.| +00011f50 c6 00 00 8b 45 fc c9 c3 55 89 e5 83 ec 10 c7 45 |....E...U......E| +00011f60 f8 00 00 00 00 8b 45 08 89 45 f4 8b 45 0c 25 00 |......E..E..E.%.| +00011f70 00 00 c0 89 45 f0 c1 6d f0 1e c7 45 fc 00 00 00 |....E..m...E....| +00011f80 00 eb 47 83 7d fc 0a 74 0c 83 7d f0 00 75 06 83 |..G.}..t..}..u..| +00011f90 7d f8 00 74 1e c7 45 f8 01 00 00 00 83 65 f0 07 |}..t..E......e..| +00011fa0 8b 45 f0 8d 48 30 8b 45 f4 8d 50 01 89 55 f4 89 |.E..H0.E..P..U..| +00011fb0 ca 88 10 c1 65 0c 03 8b 45 0c 25 00 00 00 e0 89 |....e...E.%.....| +00011fc0 45 f0 c1 6d f0 1d 83 45 fc 01 83 7d fc 0a 7e b3 |E..m...E...}..~.| +00011fd0 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 |.E.....U..E.)...| +00011fe0 c9 c3 55 89 e5 83 ec 18 8b 45 08 89 45 f4 83 ec |..U......E..E...| +00011ff0 08 ff 75 0c ff 75 f4 e8 18 00 00 00 83 c4 10 89 |..u..u..........| +00012000 45 f4 8b 45 f4 c6 00 00 8b 55 f4 8b 45 08 29 c2 |E..E.....U..E.).| +00012010 89 d0 c9 c3 55 89 e5 83 ec 18 8b 45 0c ba cd cc |....U......E....| +00012020 cc cc f7 e2 89 d0 c1 e8 03 89 45 f4 83 7d f4 00 |..........E..}..| +00012030 74 15 8b 45 f4 83 ec 08 50 ff 75 08 e8 04 fe ff |t..E....P.u.....| +00012040 ff 83 c4 10 89 45 08 8b 4d 0c ba cd cc cc cc 89 |.....E..M.......| +00012050 c8 f7 e2 c1 ea 03 89 d0 c1 e0 02 01 d0 01 c0 29 |...............)| +00012060 c1 89 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 89 55 |......H0.E..P..U| +00012070 08 89 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 ec 18 |......E...U.....| +00012080 83 7d 10 00 79 11 83 ec 0c ff 75 0c e8 4b fd ff |.}..y.....u..K..| +00012090 ff 83 c4 10 89 45 10 8b 45 14 2b 45 10 89 45 f0 |.....E..E.+E..E.| +000120a0 83 7d f0 00 7e 1d 83 7d 18 00 75 17 83 ec 04 ff |.}..~..}..u.....| +000120b0 75 1c ff 75 f0 ff 75 08 e8 5a 00 00 00 83 c4 10 |u..u..u..Z......| +000120c0 89 45 08 c7 45 f4 00 00 00 00 eb 1b 8b 55 f4 8b |.E..E........U..| +000120d0 45 0c 8d 0c 02 8b 45 08 8d 50 01 89 55 08 0f b6 |E.....E..P..U...| +000120e0 11 88 10 83 45 f4 01 8b 45 f4 3b 45 10 7c dd 83 |....E...E.;E.|..| +000120f0 7d f0 00 7e 1d 83 7d 18 00 74 17 83 ec 04 ff 75 |}..~..}..t.....u| +00012100 1c ff 75 f0 ff 75 08 e8 0b 00 00 00 83 c4 10 89 |..u..u..........| +00012110 45 08 8b 45 08 c9 c3 55 89 e5 eb 12 8b 45 08 8d |E..E...U.....E..| +00012120 50 01 89 55 08 8b 55 10 88 10 83 6d 0c 01 83 7d |P..U..U....m...}| +00012130 0c 00 7f e8 8b 45 08 5d c3 00 00 00 75 73 65 72 |.....E.]....user| +00012140 51 3a 20 61 72 67 63 20 25 64 2c 20 61 72 67 73 |Q: argc %d, args| +00012150 3a 20 00 28 6e 75 6c 6c 29 00 20 25 73 00 0a 00 |: .(null). %s...| +00012160 21 21 21 21 21 20 25 63 20 72 65 74 75 72 6e 65 |!!!!! %c returne| +00012170 64 20 66 72 6f 6d 20 62 6f 67 75 73 20 73 79 73 |d from bogus sys| +00012180 63 61 6c 6c 21 3f 21 3f 21 0a 00 43 68 69 6c 64 |call!?!?!..Child| +00012190 20 25 64 20 65 78 65 63 28 29 20 23 25 75 20 66 | %d exec() #%u f| +000121a0 61 69 6c 65 64 0a 00 00 ec 13 00 00 2a 14 00 00 |ailed.......*...| +000121b0 76 15 00 00 76 15 00 00 76 15 00 00 76 15 00 00 |v...v...v...v...| +* +000121d0 76 15 00 00 76 15 00 00 e4 14 00 00 76 15 00 00 |v...v.......v...| +000121e0 76 15 00 00 76 15 00 00 6e 14 00 00 76 15 00 00 |v...v...n...v...| +000121f0 25 15 00 00 76 15 00 00 76 15 00 00 a0 14 00 00 |%...v...v.......| +00012200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00012850 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................| +00012860 03 00 01 00 00 00 00 00 f8 18 00 00 00 00 00 00 |................| +00012870 03 00 02 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +00012880 03 00 03 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......| +00012890 03 00 04 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| +000128a0 04 00 f1 ff 09 00 00 00 00 00 00 00 00 00 00 00 |................| +000128b0 04 00 f1 ff 11 00 00 00 00 00 00 00 00 00 00 00 |................| +000128c0 04 00 f1 ff 1a 00 00 00 00 00 00 00 00 00 00 00 |................| +000128d0 04 00 f1 ff 23 00 00 00 00 00 00 00 00 00 00 00 |....#...........| +000128e0 04 00 f1 ff 2c 00 00 00 00 00 00 00 00 00 00 00 |....,...........| +000128f0 04 00 f1 ff 36 00 00 00 00 00 00 00 00 00 00 00 |....6...........| +00012900 04 00 f1 ff 3f 00 00 00 00 00 00 00 00 00 00 00 |....?...........| +00012910 04 00 f1 ff 48 00 00 00 00 00 00 00 00 00 00 00 |....H...........| +00012920 04 00 f1 ff 51 00 00 00 00 00 00 00 00 00 00 00 |....Q...........| +00012930 04 00 f1 ff 5b 00 00 00 00 00 00 00 00 00 00 00 |....[...........| +00012940 04 00 f1 ff 64 00 00 00 00 00 00 00 00 00 00 00 |....d...........| +00012950 04 00 f1 ff 6a 00 00 00 34 12 00 00 21 00 00 00 |....j...4...!...| +00012960 12 00 01 00 73 00 00 00 a5 12 00 00 00 00 00 00 |....s...........| +00012970 10 00 01 00 7b 00 00 00 19 12 00 00 1b 00 00 00 |....{...........| +00012980 12 00 01 00 82 00 00 00 9e 17 00 00 32 00 00 00 |............2...| +00012990 12 00 01 00 89 00 00 00 cd 12 00 00 00 00 00 00 |................| +000129a0 10 00 01 00 90 00 00 00 fd 12 00 00 00 00 00 00 |................| +000129b0 10 00 01 00 96 00 00 00 82 12 00 00 1b 00 00 00 |................| +000129c0 12 00 01 00 9d 00 00 00 d3 18 00 00 22 00 00 00 |............"...| +000129d0 12 00 01 00 a1 00 00 00 56 11 00 00 75 00 00 00 |........V...u...| +000129e0 12 00 01 00 a7 00 00 00 23 13 00 00 75 02 00 00 |........#...u...| +000129f0 12 00 01 00 ae 00 00 00 8a 16 00 00 8a 00 00 00 |................| +00012a00 12 00 01 00 b5 00 00 00 d0 17 00 00 66 00 00 00 |............f...| +00012a10 12 00 01 00 7c 00 00 00 c5 12 00 00 00 00 00 00 |....|...........| +00012a20 10 00 01 00 bd 00 00 00 f5 12 00 00 00 00 00 00 |................| +00012a30 10 00 01 00 c2 00 00 00 ec 11 00 00 2d 00 00 00 |............-...| +00012a40 12 00 01 00 ca 00 00 00 b5 12 00 00 00 00 00 00 |................| +00012a50 10 00 01 00 cf 00 00 00 3e 11 00 00 18 00 00 00 |........>.......| +00012a60 12 00 01 00 d4 00 00 00 55 12 00 00 2d 00 00 00 |........U...-...| +00012a70 12 00 01 00 dc 00 00 00 13 13 00 00 00 00 00 00 |................| +00012a80 10 00 01 00 e3 00 00 00 bd 12 00 00 00 00 00 00 |................| +00012a90 10 00 01 00 e8 00 00 00 e5 12 00 00 00 00 00 00 |................| +00012aa0 10 00 01 00 f0 00 00 00 01 16 00 00 89 00 00 00 |................| +00012ab0 12 00 01 00 f8 00 00 00 ad 12 00 00 00 00 00 00 |................| +00012ac0 10 00 01 00 fd 00 00 00 00 10 00 00 3e 01 00 00 |............>...| +00012ad0 12 00 01 00 02 01 00 00 d5 12 00 00 00 00 00 00 |................| +00012ae0 10 00 01 00 0a 01 00 00 36 18 00 00 9d 00 00 00 |........6.......| +00012af0 12 00 01 00 11 01 00 00 ed 12 00 00 00 00 00 00 |................| +00012b00 10 00 01 00 19 01 00 00 14 17 00 00 8a 00 00 00 |................| +00012b10 12 00 01 00 20 01 00 00 cb 11 00 00 21 00 00 00 |.... .......!...| +00012b20 12 00 01 00 29 01 00 00 dd 12 00 00 00 00 00 00 |....)...........| +00012b30 10 00 01 00 31 01 00 00 ba 15 00 00 47 00 00 00 |....1.......G...| +00012b40 12 00 01 00 4a 01 00 00 9d 12 00 00 00 00 00 00 |....J...........| +00012b50 10 00 01 00 38 01 00 00 98 15 00 00 22 00 00 00 |....8......."...| +00012b60 12 00 01 00 3f 01 00 00 05 13 00 00 00 00 00 00 |....?...........| +00012b70 10 00 01 00 45 01 00 00 0d 13 00 00 00 00 00 00 |....E...........| +00012b80 10 00 01 00 00 70 72 6f 67 51 2e 63 00 75 6c 69 |.....progQ.c.uli| +00012b90 62 63 2e 63 00 73 70 72 69 6e 74 2e 63 00 73 74 |bc.c.sprint.c.st| +00012ba0 72 6c 65 6e 2e 63 00 63 76 74 64 65 63 2e 63 00 |rlen.c.cvtdec.c.| +00012bb0 63 76 74 64 65 63 30 2e 63 00 63 76 74 68 65 78 |cvtdec0.c.cvthex| +00012bc0 2e 63 00 63 76 74 6f 63 74 2e 63 00 63 76 74 75 |.c.cvtoct.c.cvtu| +00012bd0 6e 73 2e 63 00 63 76 74 75 6e 73 30 2e 63 00 70 |ns.c.cvtuns0.c.p| +00012be0 61 64 73 74 72 2e 63 00 70 61 64 2e 63 00 73 77 |adstr.c.pad.c.sw| +00012bf0 72 69 74 65 63 68 00 77 61 69 74 70 69 64 00 63 |ritech.waitpid.c| +00012c00 77 72 69 74 65 00 63 76 74 75 6e 73 00 67 65 74 |write.cvtuns.get| +00012c10 70 69 64 00 73 6c 65 65 70 00 73 77 72 69 74 65 |pid.sleep.swrite| +00012c20 00 70 61 64 00 73 70 61 77 6e 00 73 70 72 69 6e |.pad.spawn.sprin| +00012c30 74 00 63 76 74 68 65 78 00 63 76 74 75 6e 73 30 |t.cvthex.cvtuns0| +00012c40 00 6b 69 6c 6c 00 63 77 72 69 74 65 73 00 65 78 |.kill.cwrites.ex| +00012c50 65 63 00 77 61 69 74 00 73 77 72 69 74 65 73 00 |ec.wait.swrites.| +00012c60 5f 73 74 61 72 74 00 72 65 61 64 00 67 65 74 70 |_start.read.getp| +00012c70 72 69 6f 00 63 76 74 64 65 63 30 00 66 6f 72 6b |rio.cvtdec0.fork| +00012c80 00 6d 61 69 6e 00 67 65 74 70 70 69 64 00 70 61 |.main.getppid.pa| +00012c90 64 73 74 72 00 73 65 74 70 72 69 6f 00 63 76 74 |dstr.setprio.cvt| +00012ca0 6f 63 74 00 63 77 72 69 74 65 63 68 00 67 65 74 |oct.cwritech.get| +00012cb0 74 69 6d 65 00 63 76 74 64 65 63 00 73 74 72 6c |time.cvtdec.strl| +00012cc0 65 6e 00 62 6f 67 75 73 00 66 61 6b 65 5f 65 78 |en.bogus.fake_ex| +00012cd0 69 74 00 00 2e 73 79 6d 74 61 62 00 2e 73 74 72 |it...symtab..str| +00012ce0 74 61 62 00 2e 73 68 73 74 72 74 61 62 00 2e 74 |tab..shstrtab..t| +00012cf0 65 78 74 00 2e 72 6f 64 61 74 61 00 2e 64 61 74 |ext..rodata..dat| +00012d00 61 00 2e 62 73 73 00 00 00 00 00 00 00 00 00 00 |a..bss..........| +00012d10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00012d30 1b 00 00 00 01 00 00 00 06 00 00 00 00 10 00 00 |................| +00012d40 74 00 00 00 f5 08 00 00 00 00 00 00 00 00 00 00 |t...............| +00012d50 01 00 00 00 00 00 00 00 21 00 00 00 01 00 00 00 |........!.......| +00012d60 02 00 00 00 f8 18 00 00 6c 09 00 00 c4 00 00 00 |........l.......| +00012d70 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................| +00012d80 29 00 00 00 01 00 00 00 03 00 00 00 00 20 00 00 |)............ ..| +00012d90 74 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |t...............| +00012da0 01 00 00 00 00 00 00 00 2f 00 00 00 08 00 00 00 |......../.......| +00012db0 03 00 00 00 00 20 00 00 74 10 00 00 00 00 00 00 |..... ..t.......| +00012dc0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| +00012dd0 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................| +00012de0 74 10 00 00 40 03 00 00 06 00 00 00 11 00 00 00 |t...@...........| +00012df0 04 00 00 00 10 00 00 00 09 00 00 00 03 00 00 00 |................| +00012e00 00 00 00 00 00 00 00 00 b4 13 00 00 4f 01 00 00 |............O...| +00012e10 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| +00012e20 11 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| +00012e30 03 15 00 00 34 00 00 00 00 00 00 00 00 00 00 00 |....4...........| +00012e40 01 00 00 00 00 00 00 00 7f 45 4c 46 01 01 01 00 |.........ELF....| +00012e50 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 |................| +00012e60 23 14 00 00 34 00 00 00 6c 15 00 00 00 00 00 00 |#...4...l.......| +00012e70 34 00 20 00 02 00 28 00 08 00 07 00 01 00 00 00 |4. ...(.........| +00012e80 74 00 00 00 00 10 00 00 00 10 00 00 00 10 00 00 |t...............| +00012e90 00 10 00 00 07 00 00 00 04 00 00 00 51 e5 74 64 |............Q.td| +00012ea0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00012eb0 00 00 00 00 07 00 00 00 10 00 00 00 8d 4c 24 04 |.............L$.| +00012ec0 83 e4 f0 ff 71 fc 55 89 e5 53 51 81 ec a0 00 00 |....q.U..SQ.....| +00012ed0 00 89 cb c6 45 f7 72 c7 45 f0 0a 00 00 00 c7 45 |....E.r.E......E| +00012ee0 ec 63 00 00 00 8b 03 83 f8 03 74 25 83 f8 04 74 |.c........t%...t| +00012ef0 07 83 f8 02 74 34 eb 45 8b 43 04 83 c0 0c 8b 00 |....t4.E.C......| +00012f00 83 ec 08 6a 0a 50 e8 59 06 00 00 83 c4 10 89 45 |...j.P.Y.......E| +00012f10 f0 8b 43 04 83 c0 08 8b 00 83 ec 08 6a 0a 50 e8 |..C.........j.P.| +00012f20 40 06 00 00 83 c4 10 89 45 ec 8b 43 04 83 c0 04 |@.......E..C....| +00012f30 8b 00 0f b6 00 88 45 f7 e9 a4 00 00 00 83 ec 04 |......E.........| +00012f40 ff 33 68 78 1a 00 00 8d 85 5c ff ff ff 50 e8 9c |.3hx.....\...P..| +00012f50 03 00 00 83 c4 10 83 ec 0c 8d 85 5c ff ff ff 50 |...........\...P| +00012f60 e8 53 02 00 00 83 c4 10 c7 45 e8 00 00 00 00 eb |.S.......E......| +00012f70 59 8b 03 8d 14 85 00 00 00 00 8b 43 04 01 d0 8b |Y..........C....| +00012f80 00 85 c0 74 12 8b 03 8d 14 85 00 00 00 00 8b 43 |...t...........C| +00012f90 04 01 d0 8b 00 eb 05 b8 8f 1a 00 00 83 ec 04 50 |...............P| +00012fa0 68 96 1a 00 00 8d 85 5c ff ff ff 50 e8 3e 03 00 |h......\...P.>..| +00012fb0 00 83 c4 10 83 ec 0c 8d 85 5c ff ff ff 50 e8 f5 |.........\...P..| +00012fc0 01 00 00 83 c4 10 83 45 e8 01 8b 45 e8 3b 03 7e |.......E...E.;.~| +00012fd0 a0 83 ec 0c 68 9a 1a 00 00 e8 da 01 00 00 83 c4 |....h...........| +00012fe0 10 e8 b3 02 00 00 89 45 e4 e8 b3 02 00 00 89 45 |.......E.......E| +00012ff0 e0 0f be 45 f7 83 ec 08 ff 75 e0 ff 75 e4 ff 75 |...E.....u..u..u| +00013000 ec 50 68 9c 1a 00 00 8d 85 5c ff ff ff 50 e8 dc |.Ph......\...P..| +00013010 02 00 00 83 c4 20 83 ec 0c 8d 85 5c ff ff ff 50 |..... .....\...P| +00013020 e8 fc 01 00 00 83 c4 10 8b 45 f0 69 c0 e8 03 00 |.........E.i....| +00013030 00 83 ec 0c 50 e8 8f 02 00 00 83 c4 10 83 7d ec |....P.........}.| +00013040 04 7f 63 83 45 ec 01 e8 2d 02 00 00 89 45 dc 8b |..c.E...-....E..| +00013050 45 dc 83 f8 ff 74 06 85 c0 74 86 eb 2e ff 75 dc |E....t...t....u.| +00013060 ff 75 e4 68 aa 1a 00 00 8d 85 5c ff ff ff 50 e8 |.u.h......\...P.| +00013070 7b 02 00 00 83 c4 10 83 ec 0c 8d 85 5c ff ff ff |{...........\...| +00013080 50 e8 32 01 00 00 83 c4 10 eb 1c 83 6d ec 01 8b |P.2.........m...| +00013090 45 f0 69 c0 e8 03 00 00 83 ec 0c 50 e8 28 02 00 |E.i........P.(..| +000130a0 00 83 c4 10 eb 01 90 e8 ed 01 00 00 89 45 e4 e8 |.............E..| +000130b0 ed 01 00 00 89 45 e0 0f be 45 f7 83 ec 08 ff 75 |.....E...E.....u| +000130c0 e0 ff 75 e4 ff 75 ec 50 68 9c 1a 00 00 8d 85 5c |..u..u.Ph......\| +000130d0 ff ff ff 50 e8 16 02 00 00 83 c4 20 83 ec 0c 8d |...P....... ....| +000130e0 85 5c ff ff ff 50 e8 36 01 00 00 83 c4 10 83 ec |.\...P.6........| +000130f0 0c 6a 00 e8 71 01 00 00 83 c4 10 b8 2a 00 00 00 |.j..q.......*...| +00013100 8d 65 f8 59 5b 5d 8d 61 fc c3 55 89 e5 83 ec 08 |.e.Y[].a..U.....| +00013110 83 ec 08 ff 75 08 6a 00 e8 54 01 00 00 83 c4 10 |....u.j..T......| +00013120 c9 c3 55 89 e5 81 ec 18 01 00 00 e8 49 01 00 00 |..U.........I...| +00013130 89 45 f4 83 7d f4 00 74 05 8b 45 f4 eb 57 e8 56 |.E..}..t..E..W.V| +00013140 01 00 00 89 45 f4 83 ec 08 ff 75 0c ff 75 08 e8 |....E.....u..u..| +00013150 2d 01 00 00 83 c4 10 ff 75 08 ff 75 f4 68 c1 1a |-.......u..u.h..| +00013160 00 00 8d 85 f4 fe ff ff 50 e8 81 01 00 00 83 c4 |........P.......| +00013170 10 83 ec 0c 8d 85 f4 fe ff ff 50 e8 38 00 00 00 |..........P.8...| +00013180 83 c4 10 83 ec 0c 6a ff e8 dc 00 00 00 83 c4 10 |......j.........| +00013190 b8 00 00 00 00 c9 c3 55 89 e5 83 ec 18 8b 45 08 |.......U......E.| +000131a0 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 00 e8 de |.E....j..E.Pj...| +000131b0 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 ec |........U.......| +000131c0 0c ff 75 08 e8 0d 04 00 00 83 c4 10 89 45 f4 8b |..u..........E..| +000131d0 45 f4 83 ec 04 50 ff 75 08 6a 00 e8 b1 00 00 00 |E....P.u.j......| +000131e0 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff 75 |.....U.........u| +000131f0 0c ff 75 08 6a 00 e8 96 00 00 00 83 c4 10 c9 c3 |..u.j...........| +00013200 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 6a |U......E..E....j| +00013210 01 8d 45 f4 50 6a 01 e8 75 00 00 00 83 c4 10 c9 |..E.Pj..u.......| +00013220 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 a4 03 |.U.........u....| +00013230 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 ff |......E..E....P.| +00013240 75 08 6a 01 e8 48 00 00 00 83 c4 10 c9 c3 55 89 |u.j..H........U.| +00013250 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 01 e8 |........u..u.j..| +00013260 2d 00 00 00 83 c4 10 c9 c3 b8 00 00 00 00 cd 80 |-...............| +00013270 c3 b8 01 00 00 00 cd 80 c3 b8 02 00 00 00 cd 80 |................| +00013280 c3 b8 03 00 00 00 cd 80 c3 b8 04 00 00 00 cd 80 |................| +00013290 c3 b8 05 00 00 00 cd 80 c3 b8 06 00 00 00 cd 80 |................| +000132a0 c3 b8 07 00 00 00 cd 80 c3 b8 08 00 00 00 cd 80 |................| +000132b0 c3 b8 09 00 00 00 cd 80 c3 b8 0a 00 00 00 cd 80 |................| +000132c0 c3 b8 0b 00 00 00 cd 80 c3 b8 0c 00 00 00 cd 80 |................| +000132d0 c3 b8 ad 0b 00 00 cd 80 c3 50 e8 8a ff ff ff e8 |.........P......| +000132e0 d8 fb ff ff 83 ec 0c 50 e8 7c ff ff ff eb fe 55 |.......P.|.....U| +000132f0 89 e5 83 ec 38 8d 45 0c 83 c0 04 89 45 f4 e9 3f |....8.E.....E..?| +00013300 02 00 00 80 7d f3 25 0f 85 26 02 00 00 c7 45 ec |....}.%..&....E.| +00013310 00 00 00 00 c7 45 e4 20 00 00 00 c7 45 e8 00 00 |.....E. ....E...| +00013320 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +00013330 f3 80 7d f3 2d 75 16 c7 45 ec 01 00 00 00 8b 45 |..}.-u..E......E| +00013340 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 |..P..U.....E..}.| +00013350 30 75 40 c7 45 e4 30 00 00 00 8b 45 0c 8d 50 01 |0u@.E.0....E..P.| +00013360 89 55 0c 0f b6 00 88 45 f3 eb 28 8b 55 e8 89 d0 |.U.....E..(.U...| +00013370 c1 e0 02 01 d0 01 c0 89 45 e8 0f be 45 f3 83 e8 |........E...E...| +00013380 30 01 45 e8 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |0.E..E..P..U....| +00013390 88 45 f3 80 7d f3 2f 7e 06 80 7d f3 39 7e cc 0f |.E..}./~..}.9~..| +000133a0 be 45 f3 83 e8 63 83 f8 15 0f 87 93 01 00 00 8b |.E...c..........| +000133b0 04 85 e0 1a 00 00 ff e0 8b 45 f4 8d 50 04 89 55 |.........E..P..U| +000133c0 f4 8b 00 88 45 f3 0f b6 45 f3 88 45 d0 c6 45 d1 |....E...E..E..E.| +000133d0 00 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a 01 8d |.....u..u..u.j..| +000133e0 45 d0 50 ff 75 08 e8 89 04 00 00 83 c4 20 89 45 |E.P.u........ .E| +000133f0 08 e9 4c 01 00 00 8b 45 f4 8d 50 04 89 55 f4 8b |..L....E..P..U..| +00013400 00 83 ec 08 50 8d 45 d0 50 e8 ea 01 00 00 83 c4 |....P.E.P.......| +00013410 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 |..E.....u..u..u.| +00013420 ff 75 e0 8d 45 d0 50 ff 75 08 e8 45 04 00 00 83 |.u..E.P.u..E....| +00013430 c4 20 89 45 08 e9 08 01 00 00 8b 45 f4 8d 50 04 |. .E.......E..P.| +00013440 89 55 f4 8b 00 89 45 dc 83 ec 08 ff 75 e4 ff 75 |.U....E.....u..u| +00013450 ec ff 75 e8 6a ff ff 75 dc ff 75 08 e8 13 04 00 |..u.j..u..u.....| +00013460 00 83 c4 20 89 45 08 e9 d6 00 00 00 8b 45 f4 8d |... .E.......E..| +00013470 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 |P..U......P.E.P.| +00013480 44 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 |D.......E.....u.| +00013490 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 |.u..u..u..E.P.u.| +000134a0 e8 cf 03 00 00 83 c4 20 89 45 08 e9 92 00 00 00 |....... .E......| +000134b0 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d |.E..P..U......P.| +000134c0 45 d0 50 e8 8a 02 00 00 83 c4 10 89 45 e0 83 ec |E.P.........E...| +000134d0 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 |..u..u..u..u..E.| +000134e0 50 ff 75 08 e8 8b 03 00 00 83 c4 20 89 45 08 eb |P.u........ .E..| +000134f0 51 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 |Q.E..P..U......P| +00013500 8d 45 d0 50 e8 d3 02 00 00 83 c4 10 89 45 e0 83 |.E.P.........E..| +00013510 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 |...u..u..u..u..E| +00013520 d0 50 ff 75 08 e8 4a 03 00 00 83 c4 20 89 45 08 |.P.u..J..... .E.| +00013530 90 eb 0f 8b 45 08 8d 50 01 89 55 08 0f b6 55 f3 |....E..P..U...U.| +00013540 88 10 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +00013550 f3 80 7d f3 00 0f 85 a8 fd ff ff 8b 45 08 c6 00 |..}.........E...| +00013560 00 90 c9 c3 55 89 e5 53 83 ec 14 8b 45 08 8b 4d |....U..S....E..M| +00013570 0c bb 00 00 00 00 c6 45 eb 39 c7 45 f8 01 00 00 |.......E.9.E....| +00013580 00 0f b6 10 80 fa 2d 75 0a c7 45 f8 ff ff ff ff |......-u..E.....| +00013590 83 c0 01 83 f9 0a 74 2b 89 ca 83 c2 2f 88 55 eb |......t+..../.U.| +000135a0 eb 21 0f b6 10 80 fa 2f 7e 20 0f b6 10 38 55 eb |.!...../~ ...8U.| +000135b0 7c 18 0f af d9 0f b6 10 0f be d2 01 da 8d 5a d0 ||.............Z.| +000135c0 83 c0 01 0f b6 10 84 d2 75 d8 89 d8 0f af 45 f8 |........u.....E.| +000135d0 83 c4 14 5b 5d c3 55 89 e5 53 8b 55 08 bb 00 00 |...[].U..S.U....| +000135e0 00 00 eb 03 83 c3 01 89 d0 8d 50 01 0f b6 00 84 |..........P.....| +000135f0 c0 75 f1 89 d8 5b 5d c3 55 89 e5 83 ec 18 8b 45 |.u...[].U......E| +00013600 08 89 45 f4 83 7d 0c 00 79 0f 8b 45 f4 8d 50 01 |..E..}..y..E..P.| +00013610 89 55 f4 c6 00 2d f7 5d 0c 83 ec 08 ff 75 0c ff |.U...-.].....u..| +00013620 75 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 |u..........E..E.| +00013630 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 |....U..E.).....U| +00013640 89 e5 83 ec 18 8b 4d 0c ba 67 66 66 66 89 c8 f7 |......M..gfff...| +00013650 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 89 45 f4 |.........)....E.| +00013660 83 7d f4 00 79 0e c7 45 f4 cc cc cc 0c c7 45 0c |.}..y..E......E.| +00013670 08 00 00 00 83 7d f4 00 74 14 83 ec 08 ff 75 f4 |.....}..t.....u.| +00013680 ff 75 08 e8 b7 ff ff ff 83 c4 10 89 45 08 8b 4d |.u..........E..M| +00013690 0c ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 |..gfff..........| +000136a0 f8 1f 29 c2 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 |..)..........)..| +000136b0 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 89 |....H0.E..P..U..| +000136c0 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 ec 20 c7 45 |....E...U.... .E| +000136d0 e3 30 31 32 33 c7 45 e7 34 35 36 37 c7 45 eb 38 |.0123.E.4567.E.8| +000136e0 39 41 42 c7 45 ef 43 44 45 46 c6 45 f3 00 c7 45 |9AB.E.CDEF.E...E| +000136f0 fc 00 00 00 00 c7 45 f8 00 00 00 00 eb 43 8b 45 |......E......C.E| +00013700 0c 25 00 00 00 f0 89 45 f4 83 7d fc 00 75 0c 83 |.%.....E..}..u..| +00013710 7d f4 00 75 06 83 7d f8 07 75 1e 83 45 fc 01 c1 |}..u..}..u..E...| +00013720 6d f4 1c 8b 45 08 8d 50 01 89 55 08 8d 4d e3 8b |m...E..P..U..M..| +00013730 55 f4 01 ca 0f b6 12 88 10 c1 65 0c 04 83 45 f8 |U.........e...E.| +00013740 01 83 7d f8 07 7e b7 8b 45 08 c6 00 00 8b 45 fc |..}..~..E.....E.| +00013750 c9 c3 55 89 e5 83 ec 10 c7 45 f8 00 00 00 00 8b |..U......E......| +00013760 45 08 89 45 f4 8b 45 0c 25 00 00 00 c0 89 45 f0 |E..E..E.%.....E.| +00013770 c1 6d f0 1e c7 45 fc 00 00 00 00 eb 47 83 7d fc |.m...E......G.}.| +00013780 0a 74 0c 83 7d f0 00 75 06 83 7d f8 00 74 1e c7 |.t..}..u..}..t..| +00013790 45 f8 01 00 00 00 83 65 f0 07 8b 45 f0 8d 48 30 |E......e...E..H0| +000137a0 8b 45 f4 8d 50 01 89 55 f4 89 ca 88 10 c1 65 0c |.E..P..U......e.| +000137b0 03 8b 45 0c 25 00 00 00 e0 89 45 f0 c1 6d f0 1d |..E.%.....E..m..| +000137c0 83 45 fc 01 83 7d fc 0a 7e b3 8b 45 f4 c6 00 00 |.E...}..~..E....| +000137d0 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 |.U..E.).....U...| +000137e0 ec 18 8b 45 08 89 45 f4 83 ec 08 ff 75 0c ff 75 |...E..E.....u..u| +000137f0 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 |..........E..E..| +00013800 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 |...U..E.).....U.| +00013810 e5 83 ec 18 8b 45 0c ba cd cc cc cc f7 e2 89 d0 |.....E..........| +00013820 c1 e8 03 89 45 f4 83 7d f4 00 74 15 8b 45 f4 83 |....E..}..t..E..| +00013830 ec 08 50 ff 75 08 e8 04 fe ff ff 83 c4 10 89 45 |..P.u..........E| +00013840 08 8b 4d 0c ba cd cc cc cc 89 c8 f7 e2 c1 ea 03 |..M.............| +00013850 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d |.........)......| +00013860 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 8b |H0.E..P..U......| +00013870 45 08 c9 c3 55 89 e5 83 ec 18 83 7d 10 00 79 11 |E...U......}..y.| +00013880 83 ec 0c ff 75 0c e8 4b fd ff ff 83 c4 10 89 45 |....u..K.......E| +00013890 10 8b 45 14 2b 45 10 89 45 f0 83 7d f0 00 7e 1d |..E.+E..E..}..~.| +000138a0 83 7d 18 00 75 17 83 ec 04 ff 75 1c ff 75 f0 ff |.}..u.....u..u..| +000138b0 75 08 e8 5a 00 00 00 83 c4 10 89 45 08 c7 45 f4 |u..Z.......E..E.| +000138c0 00 00 00 00 eb 1b 8b 55 f4 8b 45 0c 8d 0c 02 8b |.......U..E.....| +000138d0 45 08 8d 50 01 89 55 08 0f b6 11 88 10 83 45 f4 |E..P..U.......E.| +000138e0 01 8b 45 f4 3b 45 10 7c dd 83 7d f0 00 7e 1d 83 |..E.;E.|..}..~..| +000138f0 7d 18 00 74 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 |}..t.....u..u..u| +00013900 08 e8 0b 00 00 00 83 c4 10 89 45 08 8b 45 08 c9 |..........E..E..| +00013910 c3 55 89 e5 eb 12 8b 45 08 8d 50 01 89 55 08 8b |.U.....E..P..U..| +00013920 55 10 88 10 83 6d 0c 01 83 7d 0c 00 7f e8 8b 45 |U....m...}.....E| +00013930 08 5d c3 00 75 73 65 72 52 3a 20 61 72 67 63 20 |.]..userR: argc | +00013940 25 64 2c 20 61 72 67 73 3a 20 00 28 6e 75 6c 6c |%d, args: .(null| +00013950 29 00 20 25 73 00 0a 00 20 25 63 5b 25 64 2c 25 |). %s... %c[%d,%| +00013960 64 2c 25 64 5d 00 2a 2a 20 52 5b 25 64 5d 20 66 |d,%d].** R[%d] f| +00013970 6f 72 6b 20 63 6f 64 65 20 25 64 0a 00 43 68 69 |ork code %d..Chi| +00013980 6c 64 20 25 64 20 65 78 65 63 28 29 20 23 25 75 |ld %d exec() #%u| +00013990 20 66 61 69 6c 65 64 0a 00 00 00 00 fc 14 00 00 | failed.........| +000139a0 3a 15 00 00 86 16 00 00 86 16 00 00 86 16 00 00 |:...............| +000139b0 86 16 00 00 86 16 00 00 86 16 00 00 86 16 00 00 |................| +000139c0 86 16 00 00 86 16 00 00 86 16 00 00 f4 15 00 00 |................| +000139d0 86 16 00 00 86 16 00 00 86 16 00 00 7e 15 00 00 |............~...| +000139e0 86 16 00 00 35 16 00 00 86 16 00 00 86 16 00 00 |....5...........| +000139f0 b0 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00013a00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00013ed0 00 10 00 00 00 00 00 00 03 00 01 00 00 00 00 00 |................| +00013ee0 78 1a 00 00 00 00 00 00 03 00 02 00 00 00 00 00 |x...............| +00013ef0 00 20 00 00 00 00 00 00 03 00 03 00 00 00 00 00 |. ..............| +00013f00 00 20 00 00 00 00 00 00 03 00 04 00 01 00 00 00 |. ..............| +00013f10 00 00 00 00 00 00 00 00 04 00 f1 ff 09 00 00 00 |................| +00013f20 00 00 00 00 00 00 00 00 04 00 f1 ff 11 00 00 00 |................| +00013f30 00 00 00 00 00 00 00 00 04 00 f1 ff 1a 00 00 00 |................| +00013f40 00 00 00 00 00 00 00 00 04 00 f1 ff 24 00 00 00 |............$...| +00013f50 00 00 00 00 00 00 00 00 04 00 f1 ff 2d 00 00 00 |............-...| +00013f60 00 00 00 00 00 00 00 00 04 00 f1 ff 36 00 00 00 |............6...| +00013f70 00 00 00 00 00 00 00 00 04 00 f1 ff 40 00 00 00 |............@...| +00013f80 00 00 00 00 00 00 00 00 04 00 f1 ff 49 00 00 00 |............I...| +00013f90 00 00 00 00 00 00 00 00 04 00 f1 ff 52 00 00 00 |............R...| +00013fa0 00 00 00 00 00 00 00 00 04 00 f1 ff 5b 00 00 00 |............[...| +00013fb0 00 00 00 00 00 00 00 00 04 00 f1 ff 65 00 00 00 |............e...| +00013fc0 00 00 00 00 00 00 00 00 04 00 f1 ff 6e 00 00 00 |............n...| +00013fd0 00 00 00 00 00 00 00 00 04 00 f1 ff 74 00 00 00 |............t...| +00013fe0 44 13 00 00 21 00 00 00 12 00 01 00 7d 00 00 00 |D...!.......}...| +00013ff0 b5 13 00 00 00 00 00 00 10 00 01 00 85 00 00 00 |................| +00014000 29 13 00 00 1b 00 00 00 12 00 01 00 8c 00 00 00 |)...............| +00014010 a8 16 00 00 72 00 00 00 12 00 01 00 94 00 00 00 |....r...........| +00014020 20 19 00 00 32 00 00 00 12 00 01 00 9b 00 00 00 | ...2...........| +00014030 dd 13 00 00 00 00 00 00 10 00 01 00 a2 00 00 00 |................| +00014040 0d 14 00 00 00 00 00 00 10 00 01 00 a8 00 00 00 |................| +00014050 92 13 00 00 1b 00 00 00 12 00 01 00 af 00 00 00 |................| +00014060 55 1a 00 00 22 00 00 00 12 00 01 00 b3 00 00 00 |U..."...........| +00014070 66 12 00 00 75 00 00 00 12 00 01 00 b9 00 00 00 |f...u...........| +00014080 33 14 00 00 75 02 00 00 12 00 01 00 c0 00 00 00 |3...u...........| +00014090 0c 18 00 00 8a 00 00 00 12 00 01 00 c7 00 00 00 |................| +000140a0 52 19 00 00 66 00 00 00 12 00 01 00 86 00 00 00 |R...f...........| +000140b0 d5 13 00 00 00 00 00 00 10 00 01 00 cf 00 00 00 |................| +000140c0 05 14 00 00 00 00 00 00 10 00 01 00 d4 00 00 00 |................| +000140d0 fc 12 00 00 2d 00 00 00 12 00 01 00 dc 00 00 00 |....-...........| +000140e0 c5 13 00 00 00 00 00 00 10 00 01 00 e1 00 00 00 |................| +000140f0 4e 12 00 00 18 00 00 00 12 00 01 00 e6 00 00 00 |N...............| +00014100 65 13 00 00 2d 00 00 00 12 00 01 00 ee 00 00 00 |e...-...........| +00014110 23 14 00 00 00 00 00 00 10 00 01 00 f5 00 00 00 |#...............| +00014120 cd 13 00 00 00 00 00 00 10 00 01 00 fa 00 00 00 |................| +00014130 f5 13 00 00 00 00 00 00 10 00 01 00 02 01 00 00 |................| +00014140 83 17 00 00 89 00 00 00 12 00 01 00 0a 01 00 00 |................| +00014150 bd 13 00 00 00 00 00 00 10 00 01 00 0f 01 00 00 |................| +00014160 00 10 00 00 4e 02 00 00 12 00 01 00 14 01 00 00 |....N...........| +00014170 e5 13 00 00 00 00 00 00 10 00 01 00 1c 01 00 00 |................| +00014180 b8 19 00 00 9d 00 00 00 12 00 01 00 23 01 00 00 |............#...| +00014190 fd 13 00 00 00 00 00 00 10 00 01 00 2b 01 00 00 |............+...| +000141a0 96 18 00 00 8a 00 00 00 12 00 01 00 32 01 00 00 |............2...| +000141b0 db 12 00 00 21 00 00 00 12 00 01 00 3b 01 00 00 |....!.......;...| +000141c0 ed 13 00 00 00 00 00 00 10 00 01 00 43 01 00 00 |............C...| +000141d0 3c 17 00 00 47 00 00 00 12 00 01 00 5c 01 00 00 |<...G.......\...| +000141e0 ad 13 00 00 00 00 00 00 10 00 01 00 4a 01 00 00 |............J...| +000141f0 1a 17 00 00 22 00 00 00 12 00 01 00 51 01 00 00 |....".......Q...| +00014200 15 14 00 00 00 00 00 00 10 00 01 00 57 01 00 00 |............W...| +00014210 1d 14 00 00 00 00 00 00 10 00 01 00 00 70 72 6f |.............pro| +00014220 67 52 2e 63 00 75 6c 69 62 63 2e 63 00 73 70 72 |gR.c.ulibc.c.spr| +00014230 69 6e 74 2e 63 00 73 74 72 32 69 6e 74 2e 63 00 |int.c.str2int.c.| +00014240 73 74 72 6c 65 6e 2e 63 00 63 76 74 64 65 63 2e |strlen.c.cvtdec.| +00014250 63 00 63 76 74 64 65 63 30 2e 63 00 63 76 74 68 |c.cvtdec0.c.cvth| +00014260 65 78 2e 63 00 63 76 74 6f 63 74 2e 63 00 63 76 |ex.c.cvtoct.c.cv| +00014270 74 75 6e 73 2e 63 00 63 76 74 75 6e 73 30 2e 63 |tuns.c.cvtuns0.c| +00014280 00 70 61 64 73 74 72 2e 63 00 70 61 64 2e 63 00 |.padstr.c.pad.c.| +00014290 73 77 72 69 74 65 63 68 00 77 61 69 74 70 69 64 |swritech.waitpid| +000142a0 00 63 77 72 69 74 65 00 73 74 72 32 69 6e 74 00 |.cwrite.str2int.| +000142b0 63 76 74 75 6e 73 00 67 65 74 70 69 64 00 73 6c |cvtuns.getpid.sl| +000142c0 65 65 70 00 73 77 72 69 74 65 00 70 61 64 00 73 |eep.swrite.pad.s| +000142d0 70 61 77 6e 00 73 70 72 69 6e 74 00 63 76 74 68 |pawn.sprint.cvth| +000142e0 65 78 00 63 76 74 75 6e 73 30 00 6b 69 6c 6c 00 |ex.cvtuns0.kill.| +000142f0 63 77 72 69 74 65 73 00 65 78 65 63 00 77 61 69 |cwrites.exec.wai| +00014300 74 00 73 77 72 69 74 65 73 00 5f 73 74 61 72 74 |t.swrites._start| +00014310 00 72 65 61 64 00 67 65 74 70 72 69 6f 00 63 76 |.read.getprio.cv| +00014320 74 64 65 63 30 00 66 6f 72 6b 00 6d 61 69 6e 00 |tdec0.fork.main.| +00014330 67 65 74 70 70 69 64 00 70 61 64 73 74 72 00 73 |getppid.padstr.s| +00014340 65 74 70 72 69 6f 00 63 76 74 6f 63 74 00 63 77 |etprio.cvtoct.cw| +00014350 72 69 74 65 63 68 00 67 65 74 74 69 6d 65 00 63 |ritech.gettime.c| +00014360 76 74 64 65 63 00 73 74 72 6c 65 6e 00 62 6f 67 |vtdec.strlen.bog| +00014370 75 73 00 66 61 6b 65 5f 65 78 69 74 00 00 2e 73 |us.fake_exit...s| +00014380 79 6d 74 61 62 00 2e 73 74 72 74 61 62 00 2e 73 |ymtab..strtab..s| +00014390 68 73 74 72 74 61 62 00 2e 74 65 78 74 00 2e 72 |hstrtab..text..r| +000143a0 6f 64 61 74 61 00 2e 64 61 74 61 00 2e 62 73 73 |odata..data..bss| +000143b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +000143d0 00 00 00 00 00 00 00 00 00 00 00 00 1b 00 00 00 |................| +000143e0 01 00 00 00 06 00 00 00 00 10 00 00 74 00 00 00 |............t...| +000143f0 77 0a 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |w...............| +00014400 00 00 00 00 21 00 00 00 01 00 00 00 02 00 00 00 |....!...........| +00014410 78 1a 00 00 ec 0a 00 00 c0 00 00 00 00 00 00 00 |x...............| +00014420 00 00 00 00 04 00 00 00 00 00 00 00 29 00 00 00 |............)...| +00014430 01 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +00014440 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +00014450 00 00 00 00 2f 00 00 00 08 00 00 00 03 00 00 00 |..../...........| +00014460 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +00014470 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 |................| +00014480 02 00 00 00 00 00 00 00 00 00 00 00 74 10 00 00 |............t...| +00014490 60 03 00 00 06 00 00 00 12 00 00 00 04 00 00 00 |`...............| +000144a0 10 00 00 00 09 00 00 00 03 00 00 00 00 00 00 00 |................| +000144b0 00 00 00 00 d4 13 00 00 61 01 00 00 00 00 00 00 |........a.......| +000144c0 00 00 00 00 01 00 00 00 00 00 00 00 11 00 00 00 |................| +000144d0 03 00 00 00 00 00 00 00 00 00 00 00 35 15 00 00 |............5...| +000144e0 34 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |4...............| +000144f0 00 00 00 00 00 00 00 00 7f 45 4c 46 01 01 01 00 |.........ELF....| +00014500 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 |................| +00014510 43 13 00 00 34 00 00 00 6c 15 00 00 00 00 00 00 |C...4...l.......| +00014520 34 00 20 00 02 00 28 00 08 00 07 00 01 00 00 00 |4. ...(.........| +00014530 74 00 00 00 00 10 00 00 00 10 00 00 00 10 00 00 |t...............| +00014540 00 10 00 00 07 00 00 00 04 00 00 00 51 e5 74 64 |............Q.td| +00014550 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00014560 00 00 00 00 07 00 00 00 10 00 00 00 8d 4c 24 04 |.............L$.| +00014570 83 e4 f0 ff 71 fc 55 89 e5 53 51 81 ec 90 00 00 |....q.U..SQ.....| +00014580 00 89 cb c6 45 ef 73 c7 45 f4 14 00 00 00 8b 03 |....E.s.E.......| +00014590 83 f8 02 74 1e 83 f8 03 75 2c 8b 43 04 83 c0 08 |...t....u,.C....| +000145a0 8b 00 83 ec 08 6a 0a 50 e8 87 05 00 00 83 c4 10 |.....j.P........| +000145b0 89 45 f4 8b 43 04 83 c0 04 8b 00 0f b6 00 88 45 |.E..C..........E| +000145c0 ef e9 a4 00 00 00 83 ec 04 ff 33 68 98 19 00 00 |..........3h....| +000145d0 8d 85 6f ff ff ff 50 e8 e3 02 00 00 83 c4 10 83 |..o...P.........| +000145e0 ec 0c 8d 85 6f ff ff ff 50 e8 9a 01 00 00 83 c4 |....o...P.......| +000145f0 10 c7 45 f0 00 00 00 00 eb 59 8b 03 8d 14 85 00 |..E......Y......| +00014600 00 00 00 8b 43 04 01 d0 8b 00 85 c0 74 12 8b 03 |....C.......t...| +00014610 8d 14 85 00 00 00 00 8b 43 04 01 d0 8b 00 eb 05 |........C.......| +00014620 b8 af 19 00 00 83 ec 04 50 68 b6 19 00 00 8d 85 |........Ph......| +00014630 6f ff ff ff 50 e8 85 02 00 00 83 c4 10 83 ec 0c |o...P...........| +00014640 8d 85 6f ff ff ff 50 e8 3c 01 00 00 83 c4 10 83 |..o...P.<.......| +00014650 45 f0 01 8b 45 f0 3b 03 7e a0 83 ec 0c 68 ba 19 |E...E.;.~....h..| +00014660 00 00 e8 21 01 00 00 83 c4 10 83 ec 04 6a 01 8d |...!.........j..| +00014670 45 ef 50 6a 01 e8 e7 01 00 00 83 c4 10 8b 45 f4 |E.Pj..........E.| +00014680 69 c0 e8 03 00 00 50 ff 75 f4 68 bc 19 00 00 8d |i.....P.u.h.....| +00014690 85 6f ff ff ff 50 e8 24 02 00 00 83 c4 10 83 ec |.o...P.$........| +000146a0 0c 8d 85 6f ff ff ff 50 e8 db 00 00 00 83 c4 10 |...o...P........| +000146b0 8b 45 f4 69 c0 e8 03 00 00 83 ec 0c 50 e8 d7 01 |.E.i........P...| +000146c0 00 00 83 c4 10 83 ec 04 6a 01 8d 45 ef 50 6a 01 |........j..E.Pj.| +000146d0 e8 8c 01 00 00 83 c4 10 eb d6 55 89 e5 83 ec 08 |..........U.....| +000146e0 83 ec 08 ff 75 08 6a 00 e8 54 01 00 00 83 c4 10 |....u.j..T......| +000146f0 c9 c3 55 89 e5 81 ec 18 01 00 00 e8 49 01 00 00 |..U.........I...| +00014700 89 45 f4 83 7d f4 00 74 05 8b 45 f4 eb 57 e8 56 |.E..}..t..E..W.V| +00014710 01 00 00 89 45 f4 83 ec 08 ff 75 0c ff 75 08 e8 |....E.....u..u..| +00014720 2d 01 00 00 83 c4 10 ff 75 08 ff 75 f4 68 d3 19 |-.......u..u.h..| +00014730 00 00 8d 85 f4 fe ff ff 50 e8 81 01 00 00 83 c4 |........P.......| +00014740 10 83 ec 0c 8d 85 f4 fe ff ff 50 e8 38 00 00 00 |..........P.8...| +00014750 83 c4 10 83 ec 0c 6a ff e8 dc 00 00 00 83 c4 10 |......j.........| +00014760 b8 00 00 00 00 c9 c3 55 89 e5 83 ec 18 8b 45 08 |.......U......E.| +00014770 88 45 f4 83 ec 04 6a 01 8d 45 f4 50 6a 00 e8 de |.E....j..E.Pj...| +00014780 00 00 00 83 c4 10 c9 c3 55 89 e5 83 ec 18 83 ec |........U.......| +00014790 0c ff 75 08 e8 0d 04 00 00 83 c4 10 89 45 f4 8b |..u..........E..| +000147a0 45 f4 83 ec 04 50 ff 75 08 6a 00 e8 b1 00 00 00 |E....P.u.j......| +000147b0 83 c4 10 c9 c3 55 89 e5 83 ec 08 83 ec 04 ff 75 |.....U.........u| +000147c0 0c ff 75 08 6a 00 e8 96 00 00 00 83 c4 10 c9 c3 |..u.j...........| +000147d0 55 89 e5 83 ec 18 8b 45 08 88 45 f4 83 ec 04 6a |U......E..E....j| +000147e0 01 8d 45 f4 50 6a 01 e8 75 00 00 00 83 c4 10 c9 |..E.Pj..u.......| +000147f0 c3 55 89 e5 83 ec 18 83 ec 0c ff 75 08 e8 a4 03 |.U.........u....| +00014800 00 00 83 c4 10 89 45 f4 8b 45 f4 83 ec 04 50 ff |......E..E....P.| +00014810 75 08 6a 01 e8 48 00 00 00 83 c4 10 c9 c3 55 89 |u.j..H........U.| +00014820 e5 83 ec 08 83 ec 04 ff 75 0c ff 75 08 6a 01 e8 |........u..u.j..| +00014830 2d 00 00 00 83 c4 10 c9 c3 b8 00 00 00 00 cd 80 |-...............| +00014840 c3 b8 01 00 00 00 cd 80 c3 b8 02 00 00 00 cd 80 |................| +00014850 c3 b8 03 00 00 00 cd 80 c3 b8 04 00 00 00 cd 80 |................| +00014860 c3 b8 05 00 00 00 cd 80 c3 b8 06 00 00 00 cd 80 |................| +00014870 c3 b8 07 00 00 00 cd 80 c3 b8 08 00 00 00 cd 80 |................| +00014880 c3 b8 09 00 00 00 cd 80 c3 b8 0a 00 00 00 cd 80 |................| +00014890 c3 b8 0b 00 00 00 cd 80 c3 b8 0c 00 00 00 cd 80 |................| +000148a0 c3 b8 ad 0b 00 00 cd 80 c3 50 e8 8a ff ff ff e8 |.........P......| +000148b0 b8 fc ff ff 83 ec 0c 50 e8 7c ff ff ff eb fe 55 |.......P.|.....U| +000148c0 89 e5 83 ec 38 8d 45 0c 83 c0 04 89 45 f4 e9 3f |....8.E.....E..?| +000148d0 02 00 00 80 7d f3 25 0f 85 26 02 00 00 c7 45 ec |....}.%..&....E.| +000148e0 00 00 00 00 c7 45 e4 20 00 00 00 c7 45 e8 00 00 |.....E. ....E...| +000148f0 00 00 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +00014900 f3 80 7d f3 2d 75 16 c7 45 ec 01 00 00 00 8b 45 |..}.-u..E......E| +00014910 0c 8d 50 01 89 55 0c 0f b6 00 88 45 f3 80 7d f3 |..P..U.....E..}.| +00014920 30 75 40 c7 45 e4 30 00 00 00 8b 45 0c 8d 50 01 |0u@.E.0....E..P.| +00014930 89 55 0c 0f b6 00 88 45 f3 eb 28 8b 55 e8 89 d0 |.U.....E..(.U...| +00014940 c1 e0 02 01 d0 01 c0 89 45 e8 0f be 45 f3 83 e8 |........E...E...| +00014950 30 01 45 e8 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 |0.E..E..P..U....| +00014960 88 45 f3 80 7d f3 2f 7e 06 80 7d f3 39 7e cc 0f |.E..}./~..}.9~..| +00014970 be 45 f3 83 e8 63 83 f8 15 0f 87 93 01 00 00 8b |.E...c..........| +00014980 04 85 f0 19 00 00 ff e0 8b 45 f4 8d 50 04 89 55 |.........E..P..U| +00014990 f4 8b 00 88 45 f3 0f b6 45 f3 88 45 d0 c6 45 d1 |....E...E..E..E.| +000149a0 00 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 6a 01 8d |.....u..u..u.j..| +000149b0 45 d0 50 ff 75 08 e8 89 04 00 00 83 c4 20 89 45 |E.P.u........ .E| +000149c0 08 e9 4c 01 00 00 8b 45 f4 8d 50 04 89 55 f4 8b |..L....E..P..U..| +000149d0 00 83 ec 08 50 8d 45 d0 50 e8 ea 01 00 00 83 c4 |....P.E.P.......| +000149e0 10 89 45 e0 83 ec 08 ff 75 e4 ff 75 ec ff 75 e8 |..E.....u..u..u.| +000149f0 ff 75 e0 8d 45 d0 50 ff 75 08 e8 45 04 00 00 83 |.u..E.P.u..E....| +00014a00 c4 20 89 45 08 e9 08 01 00 00 8b 45 f4 8d 50 04 |. .E.......E..P.| +00014a10 89 55 f4 8b 00 89 45 dc 83 ec 08 ff 75 e4 ff 75 |.U....E.....u..u| +00014a20 ec ff 75 e8 6a ff ff 75 dc ff 75 08 e8 13 04 00 |..u.j..u..u.....| +00014a30 00 83 c4 20 89 45 08 e9 d6 00 00 00 8b 45 f4 8d |... .E.......E..| +00014a40 50 04 89 55 f4 8b 00 83 ec 08 50 8d 45 d0 50 e8 |P..U......P.E.P.| +00014a50 44 02 00 00 83 c4 10 89 45 e0 83 ec 08 ff 75 e4 |D.......E.....u.| +00014a60 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 50 ff 75 08 |.u..u..u..E.P.u.| +00014a70 e8 cf 03 00 00 83 c4 20 89 45 08 e9 92 00 00 00 |....... .E......| +00014a80 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 8d |.E..P..U......P.| +00014a90 45 d0 50 e8 8a 02 00 00 83 c4 10 89 45 e0 83 ec |E.P.........E...| +00014aa0 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 d0 |..u..u..u..u..E.| +00014ab0 50 ff 75 08 e8 8b 03 00 00 83 c4 20 89 45 08 eb |P.u........ .E..| +00014ac0 51 8b 45 f4 8d 50 04 89 55 f4 8b 00 83 ec 08 50 |Q.E..P..U......P| +00014ad0 8d 45 d0 50 e8 d3 02 00 00 83 c4 10 89 45 e0 83 |.E.P.........E..| +00014ae0 ec 08 ff 75 e4 ff 75 ec ff 75 e8 ff 75 e0 8d 45 |...u..u..u..u..E| +00014af0 d0 50 ff 75 08 e8 4a 03 00 00 83 c4 20 89 45 08 |.P.u..J..... .E.| +00014b00 90 eb 0f 8b 45 08 8d 50 01 89 55 08 0f b6 55 f3 |....E..P..U...U.| +00014b10 88 10 8b 45 0c 8d 50 01 89 55 0c 0f b6 00 88 45 |...E..P..U.....E| +00014b20 f3 80 7d f3 00 0f 85 a8 fd ff ff 8b 45 08 c6 00 |..}.........E...| +00014b30 00 90 c9 c3 55 89 e5 53 83 ec 14 8b 45 08 8b 4d |....U..S....E..M| +00014b40 0c bb 00 00 00 00 c6 45 eb 39 c7 45 f8 01 00 00 |.......E.9.E....| +00014b50 00 0f b6 10 80 fa 2d 75 0a c7 45 f8 ff ff ff ff |......-u..E.....| +00014b60 83 c0 01 83 f9 0a 74 2b 89 ca 83 c2 2f 88 55 eb |......t+..../.U.| +00014b70 eb 21 0f b6 10 80 fa 2f 7e 20 0f b6 10 38 55 eb |.!...../~ ...8U.| +00014b80 7c 18 0f af d9 0f b6 10 0f be d2 01 da 8d 5a d0 ||.............Z.| +00014b90 83 c0 01 0f b6 10 84 d2 75 d8 89 d8 0f af 45 f8 |........u.....E.| +00014ba0 83 c4 14 5b 5d c3 55 89 e5 53 8b 55 08 bb 00 00 |...[].U..S.U....| +00014bb0 00 00 eb 03 83 c3 01 89 d0 8d 50 01 0f b6 00 84 |..........P.....| +00014bc0 c0 75 f1 89 d8 5b 5d c3 55 89 e5 83 ec 18 8b 45 |.u...[].U......E| +00014bd0 08 89 45 f4 83 7d 0c 00 79 0f 8b 45 f4 8d 50 01 |..E..}..y..E..P.| +00014be0 89 55 f4 c6 00 2d f7 5d 0c 83 ec 08 ff 75 0c ff |.U...-.].....u..| +00014bf0 75 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 |u..........E..E.| +00014c00 c6 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 |....U..E.).....U| +00014c10 89 e5 83 ec 18 8b 4d 0c ba 67 66 66 66 89 c8 f7 |......M..gfff...| +00014c20 ea c1 fa 02 89 c8 c1 f8 1f 29 c2 89 d0 89 45 f4 |.........)....E.| +00014c30 83 7d f4 00 79 0e c7 45 f4 cc cc cc 0c c7 45 0c |.}..y..E......E.| +00014c40 08 00 00 00 83 7d f4 00 74 14 83 ec 08 ff 75 f4 |.....}..t.....u.| +00014c50 ff 75 08 e8 b7 ff ff ff 83 c4 10 89 45 08 8b 4d |.u..........E..M| +00014c60 0c ba 67 66 66 66 89 c8 f7 ea c1 fa 02 89 c8 c1 |..gfff..........| +00014c70 f8 1f 29 c2 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 |..)..........)..| +00014c80 ca 89 d0 8d 48 30 8b 45 08 8d 50 01 89 55 08 89 |....H0.E..P..U..| +00014c90 ca 88 10 8b 45 08 c9 c3 55 89 e5 83 ec 20 c7 45 |....E...U.... .E| +00014ca0 e3 30 31 32 33 c7 45 e7 34 35 36 37 c7 45 eb 38 |.0123.E.4567.E.8| +00014cb0 39 41 42 c7 45 ef 43 44 45 46 c6 45 f3 00 c7 45 |9AB.E.CDEF.E...E| +00014cc0 fc 00 00 00 00 c7 45 f8 00 00 00 00 eb 43 8b 45 |......E......C.E| +00014cd0 0c 25 00 00 00 f0 89 45 f4 83 7d fc 00 75 0c 83 |.%.....E..}..u..| +00014ce0 7d f4 00 75 06 83 7d f8 07 75 1e 83 45 fc 01 c1 |}..u..}..u..E...| +00014cf0 6d f4 1c 8b 45 08 8d 50 01 89 55 08 8d 4d e3 8b |m...E..P..U..M..| +00014d00 55 f4 01 ca 0f b6 12 88 10 c1 65 0c 04 83 45 f8 |U.........e...E.| +00014d10 01 83 7d f8 07 7e b7 8b 45 08 c6 00 00 8b 45 fc |..}..~..E.....E.| +00014d20 c9 c3 55 89 e5 83 ec 10 c7 45 f8 00 00 00 00 8b |..U......E......| +00014d30 45 08 89 45 f4 8b 45 0c 25 00 00 00 c0 89 45 f0 |E..E..E.%.....E.| +00014d40 c1 6d f0 1e c7 45 fc 00 00 00 00 eb 47 83 7d fc |.m...E......G.}.| +00014d50 0a 74 0c 83 7d f0 00 75 06 83 7d f8 00 74 1e c7 |.t..}..u..}..t..| +00014d60 45 f8 01 00 00 00 83 65 f0 07 8b 45 f0 8d 48 30 |E......e...E..H0| +00014d70 8b 45 f4 8d 50 01 89 55 f4 89 ca 88 10 c1 65 0c |.E..P..U......e.| +00014d80 03 8b 45 0c 25 00 00 00 e0 89 45 f0 c1 6d f0 1d |..E.%.....E..m..| +00014d90 83 45 fc 01 83 7d fc 0a 7e b3 8b 45 f4 c6 00 00 |.E...}..~..E....| +00014da0 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 e5 83 |.U..E.).....U...| +00014db0 ec 18 8b 45 08 89 45 f4 83 ec 08 ff 75 0c ff 75 |...E..E.....u..u| +00014dc0 f4 e8 18 00 00 00 83 c4 10 89 45 f4 8b 45 f4 c6 |..........E..E..| +00014dd0 00 00 8b 55 f4 8b 45 08 29 c2 89 d0 c9 c3 55 89 |...U..E.).....U.| +00014de0 e5 83 ec 18 8b 45 0c ba cd cc cc cc f7 e2 89 d0 |.....E..........| +00014df0 c1 e8 03 89 45 f4 83 7d f4 00 74 15 8b 45 f4 83 |....E..}..t..E..| +00014e00 ec 08 50 ff 75 08 e8 04 fe ff ff 83 c4 10 89 45 |..P.u..........E| +00014e10 08 8b 4d 0c ba cd cc cc cc 89 c8 f7 e2 c1 ea 03 |..M.............| +00014e20 89 d0 c1 e0 02 01 d0 01 c0 29 c1 89 ca 89 d0 8d |.........)......| +00014e30 48 30 8b 45 08 8d 50 01 89 55 08 89 ca 88 10 8b |H0.E..P..U......| +00014e40 45 08 c9 c3 55 89 e5 83 ec 18 83 7d 10 00 79 11 |E...U......}..y.| +00014e50 83 ec 0c ff 75 0c e8 4b fd ff ff 83 c4 10 89 45 |....u..K.......E| +00014e60 10 8b 45 14 2b 45 10 89 45 f0 83 7d f0 00 7e 1d |..E.+E..E..}..~.| +00014e70 83 7d 18 00 75 17 83 ec 04 ff 75 1c ff 75 f0 ff |.}..u.....u..u..| +00014e80 75 08 e8 5a 00 00 00 83 c4 10 89 45 08 c7 45 f4 |u..Z.......E..E.| +00014e90 00 00 00 00 eb 1b 8b 55 f4 8b 45 0c 8d 0c 02 8b |.......U..E.....| +00014ea0 45 08 8d 50 01 89 55 08 0f b6 11 88 10 83 45 f4 |E..P..U.......E.| +00014eb0 01 8b 45 f4 3b 45 10 7c dd 83 7d f0 00 7e 1d 83 |..E.;E.|..}..~..| +00014ec0 7d 18 00 74 17 83 ec 04 ff 75 1c ff 75 f0 ff 75 |}..t.....u..u..u| +00014ed0 08 e8 0b 00 00 00 83 c4 10 89 45 08 8b 45 08 c9 |..........E..E..| +00014ee0 c3 55 89 e5 eb 12 8b 45 08 8d 50 01 89 55 08 8b |.U.....E..P..U..| +00014ef0 55 10 88 10 83 6d 0c 01 83 7d 0c 00 7f e8 8b 45 |U....m...}.....E| +00014f00 08 5d c3 00 75 73 65 72 53 3a 20 61 72 67 63 20 |.]..userS: argc | +00014f10 25 64 2c 20 61 72 67 73 3a 20 00 28 6e 75 6c 6c |%d, args: .(null| +00014f20 29 00 20 25 73 00 0a 00 75 73 65 72 53 20 73 6c |). %s...userS sl| +00014f30 65 65 70 69 6e 67 20 25 64 28 25 64 29 0a 00 43 |eeping %d(%d)..C| +00014f40 68 69 6c 64 20 25 64 20 65 78 65 63 28 29 20 23 |hild %d exec() #| +00014f50 25 75 20 66 61 69 6c 65 64 0a 00 00 1c 14 00 00 |%u failed.......| +00014f60 5a 14 00 00 a6 15 00 00 a6 15 00 00 a6 15 00 00 |Z...............| +00014f70 a6 15 00 00 a6 15 00 00 a6 15 00 00 a6 15 00 00 |................| +00014f80 a6 15 00 00 a6 15 00 00 a6 15 00 00 14 15 00 00 |................| +00014f90 a6 15 00 00 a6 15 00 00 a6 15 00 00 9e 14 00 00 |................| +00014fa0 a6 15 00 00 55 15 00 00 a6 15 00 00 a6 15 00 00 |....U...........| +00014fb0 d0 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00014fc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00015580 00 10 00 00 00 00 00 00 03 00 01 00 00 00 00 00 |................| +00015590 98 19 00 00 00 00 00 00 03 00 02 00 00 00 00 00 |................| +000155a0 00 20 00 00 00 00 00 00 03 00 03 00 00 00 00 00 |. ..............| +000155b0 00 20 00 00 00 00 00 00 03 00 04 00 01 00 00 00 |. ..............| +000155c0 00 00 00 00 00 00 00 00 04 00 f1 ff 09 00 00 00 |................| +000155d0 00 00 00 00 00 00 00 00 04 00 f1 ff 11 00 00 00 |................| +000155e0 00 00 00 00 00 00 00 00 04 00 f1 ff 1a 00 00 00 |................| +000155f0 00 00 00 00 00 00 00 00 04 00 f1 ff 24 00 00 00 |............$...| +00015600 00 00 00 00 00 00 00 00 04 00 f1 ff 2d 00 00 00 |............-...| +00015610 00 00 00 00 00 00 00 00 04 00 f1 ff 36 00 00 00 |............6...| +00015620 00 00 00 00 00 00 00 00 04 00 f1 ff 40 00 00 00 |............@...| +00015630 00 00 00 00 00 00 00 00 04 00 f1 ff 49 00 00 00 |............I...| +00015640 00 00 00 00 00 00 00 00 04 00 f1 ff 52 00 00 00 |............R...| +00015650 00 00 00 00 00 00 00 00 04 00 f1 ff 5b 00 00 00 |............[...| +00015660 00 00 00 00 00 00 00 00 04 00 f1 ff 65 00 00 00 |............e...| +00015670 00 00 00 00 00 00 00 00 04 00 f1 ff 6e 00 00 00 |............n...| +00015680 00 00 00 00 00 00 00 00 04 00 f1 ff 74 00 00 00 |............t...| +00015690 64 12 00 00 21 00 00 00 12 00 01 00 7d 00 00 00 |d...!.......}...| +000156a0 d5 12 00 00 00 00 00 00 10 00 01 00 85 00 00 00 |................| +000156b0 49 12 00 00 1b 00 00 00 12 00 01 00 8c 00 00 00 |I...............| +000156c0 c8 15 00 00 72 00 00 00 12 00 01 00 94 00 00 00 |....r...........| +000156d0 40 18 00 00 32 00 00 00 12 00 01 00 9b 00 00 00 |@...2...........| +000156e0 fd 12 00 00 00 00 00 00 10 00 01 00 a2 00 00 00 |................| +000156f0 2d 13 00 00 00 00 00 00 10 00 01 00 a8 00 00 00 |-...............| +00015700 b2 12 00 00 1b 00 00 00 12 00 01 00 af 00 00 00 |................| +00015710 75 19 00 00 22 00 00 00 12 00 01 00 b3 00 00 00 |u..."...........| +00015720 86 11 00 00 75 00 00 00 12 00 01 00 b9 00 00 00 |....u...........| +00015730 53 13 00 00 75 02 00 00 12 00 01 00 c0 00 00 00 |S...u...........| +00015740 2c 17 00 00 8a 00 00 00 12 00 01 00 c7 00 00 00 |,...............| +00015750 72 18 00 00 66 00 00 00 12 00 01 00 86 00 00 00 |r...f...........| +00015760 f5 12 00 00 00 00 00 00 10 00 01 00 cf 00 00 00 |................| +00015770 25 13 00 00 00 00 00 00 10 00 01 00 d4 00 00 00 |%...............| +00015780 1c 12 00 00 2d 00 00 00 12 00 01 00 dc 00 00 00 |....-...........| +00015790 e5 12 00 00 00 00 00 00 10 00 01 00 e1 00 00 00 |................| +000157a0 6e 11 00 00 18 00 00 00 12 00 01 00 e6 00 00 00 |n...............| +000157b0 85 12 00 00 2d 00 00 00 12 00 01 00 ee 00 00 00 |....-...........| +000157c0 43 13 00 00 00 00 00 00 10 00 01 00 f5 00 00 00 |C...............| +000157d0 ed 12 00 00 00 00 00 00 10 00 01 00 fa 00 00 00 |................| +000157e0 15 13 00 00 00 00 00 00 10 00 01 00 02 01 00 00 |................| +000157f0 a3 16 00 00 89 00 00 00 12 00 01 00 0a 01 00 00 |................| +00015800 dd 12 00 00 00 00 00 00 10 00 01 00 0f 01 00 00 |................| +00015810 00 10 00 00 6e 01 00 00 12 00 01 00 14 01 00 00 |....n...........| +00015820 05 13 00 00 00 00 00 00 10 00 01 00 1c 01 00 00 |................| +00015830 d8 18 00 00 9d 00 00 00 12 00 01 00 23 01 00 00 |............#...| +00015840 1d 13 00 00 00 00 00 00 10 00 01 00 2b 01 00 00 |............+...| +00015850 b6 17 00 00 8a 00 00 00 12 00 01 00 32 01 00 00 |............2...| +00015860 fb 11 00 00 21 00 00 00 12 00 01 00 3b 01 00 00 |....!.......;...| +00015870 0d 13 00 00 00 00 00 00 10 00 01 00 43 01 00 00 |............C...| +00015880 5c 16 00 00 47 00 00 00 12 00 01 00 5c 01 00 00 |\...G.......\...| +00015890 cd 12 00 00 00 00 00 00 10 00 01 00 4a 01 00 00 |............J...| +000158a0 3a 16 00 00 22 00 00 00 12 00 01 00 51 01 00 00 |:...".......Q...| +000158b0 35 13 00 00 00 00 00 00 10 00 01 00 57 01 00 00 |5...........W...| +000158c0 3d 13 00 00 00 00 00 00 10 00 01 00 00 70 72 6f |=............pro| +000158d0 67 53 2e 63 00 75 6c 69 62 63 2e 63 00 73 70 72 |gS.c.ulibc.c.spr| +000158e0 69 6e 74 2e 63 00 73 74 72 32 69 6e 74 2e 63 00 |int.c.str2int.c.| +000158f0 73 74 72 6c 65 6e 2e 63 00 63 76 74 64 65 63 2e |strlen.c.cvtdec.| +00015900 63 00 63 76 74 64 65 63 30 2e 63 00 63 76 74 68 |c.cvtdec0.c.cvth| +00015910 65 78 2e 63 00 63 76 74 6f 63 74 2e 63 00 63 76 |ex.c.cvtoct.c.cv| +00015920 74 75 6e 73 2e 63 00 63 76 74 75 6e 73 30 2e 63 |tuns.c.cvtuns0.c| +00015930 00 70 61 64 73 74 72 2e 63 00 70 61 64 2e 63 00 |.padstr.c.pad.c.| +00015940 73 77 72 69 74 65 63 68 00 77 61 69 74 70 69 64 |swritech.waitpid| +00015950 00 63 77 72 69 74 65 00 73 74 72 32 69 6e 74 00 |.cwrite.str2int.| +00015960 63 76 74 75 6e 73 00 67 65 74 70 69 64 00 73 6c |cvtuns.getpid.sl| +00015970 65 65 70 00 73 77 72 69 74 65 00 70 61 64 00 73 |eep.swrite.pad.s| +00015980 70 61 77 6e 00 73 70 72 69 6e 74 00 63 76 74 68 |pawn.sprint.cvth| +00015990 65 78 00 63 76 74 75 6e 73 30 00 6b 69 6c 6c 00 |ex.cvtuns0.kill.| +000159a0 63 77 72 69 74 65 73 00 65 78 65 63 00 77 61 69 |cwrites.exec.wai| +000159b0 74 00 73 77 72 69 74 65 73 00 5f 73 74 61 72 74 |t.swrites._start| +000159c0 00 72 65 61 64 00 67 65 74 70 72 69 6f 00 63 76 |.read.getprio.cv| +000159d0 74 64 65 63 30 00 66 6f 72 6b 00 6d 61 69 6e 00 |tdec0.fork.main.| +000159e0 67 65 74 70 70 69 64 00 70 61 64 73 74 72 00 73 |getppid.padstr.s| +000159f0 65 74 70 72 69 6f 00 63 76 74 6f 63 74 00 63 77 |etprio.cvtoct.cw| +00015a00 72 69 74 65 63 68 00 67 65 74 74 69 6d 65 00 63 |ritech.gettime.c| +00015a10 76 74 64 65 63 00 73 74 72 6c 65 6e 00 62 6f 67 |vtdec.strlen.bog| +00015a20 75 73 00 66 61 6b 65 5f 65 78 69 74 00 00 2e 73 |us.fake_exit...s| +00015a30 79 6d 74 61 62 00 2e 73 74 72 74 61 62 00 2e 73 |ymtab..strtab..s| +00015a40 68 73 74 72 74 61 62 00 2e 74 65 78 74 00 2e 72 |hstrtab..text..r| +00015a50 6f 64 61 74 61 00 2e 64 61 74 61 00 2e 62 73 73 |odata..data..bss| +00015a60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00015a80 00 00 00 00 00 00 00 00 00 00 00 00 1b 00 00 00 |................| +00015a90 01 00 00 00 06 00 00 00 00 10 00 00 74 00 00 00 |............t...| +00015aa0 97 09 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +00015ab0 00 00 00 00 21 00 00 00 01 00 00 00 02 00 00 00 |....!...........| +00015ac0 98 19 00 00 0c 0a 00 00 b0 00 00 00 00 00 00 00 |................| +00015ad0 00 00 00 00 04 00 00 00 00 00 00 00 29 00 00 00 |............)...| +00015ae0 01 00 00 00 03 00 00 00 00 20 00 00 74 10 00 00 |......... ..t...| +00015af0 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| +00015b00 00 00 00 00 2f 00 00 00 08 00 00 00 03 00 00 00 |..../...........| +00015b10 00 20 00 00 74 10 00 00 00 00 00 00 00 00 00 00 |. ..t...........| +00015b20 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 |................| +00015b30 02 00 00 00 00 00 00 00 00 00 00 00 74 10 00 00 |............t...| +00015b40 60 03 00 00 06 00 00 00 12 00 00 00 04 00 00 00 |`...............| +00015b50 10 00 00 00 09 00 00 00 03 00 00 00 00 00 00 00 |................| +00015b60 00 00 00 00 d4 13 00 00 61 01 00 00 00 00 00 00 |........a.......| +00015b70 00 00 00 00 01 00 00 00 00 00 00 00 11 00 00 00 |................| +00015b80 03 00 00 00 00 00 00 00 00 00 00 00 35 15 00 00 |............5...| +00015b90 34 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |4...............| +00015ba0 00 00 00 00 00 00 00 00 7f 45 4c 46 01 01 01 00 |.........ELF....| +00015bb0 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 |................| +00015bc0 40 16 00 00 34 00 00 00 6c 15 00 00 00 00 00 00 |@...4...l.......| +00015bd0 34 00 20 00 02 00 28 00 08 00 07 00 01 00 00 00 |4. ...(.........| +00015be0 74 00 00 00 00 10 00 00 00 10 00 00 00 10 00 00 |t...............| +00015bf0 00 10 00 00 07 00 00 00 04 00 00 00 51 e5 74 64 |............Q.td| +00015c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00015c10 00 00 00 00 07 00 00 00 10 00 00 00 8d 4c 24 04 |.............L$.| +00015c20 83 e4 f0 ff 71 fc 55 89 e5 53 51 81 ec a0 01 00 |....q.U..SQ.....| +00015c30 00 89 cb c7 45 f4 03 00 00 00 c6 45 cb 36 c7 45 |....E......E.6.E| +00015c40 d0 08 00 00 00 c6 45 f3 01 c6 45 f2 01 c7 45 ec |......E...E...E.| +00015c50 00 00 00 00 c7 85 7c fe ff ff 2a 3f 2a 00 8b 03 |......|...*?*...| +00015c60 83 f8 03 74 32 83 f8 04 74 07 83 f8 02 74 41 eb |...t2...t....tA.| +00015c70 52 8b 43 04 83 c0 0c 8b 00 0f b6 00 3c 6b 0f 95 |R.C.........> 12) & 0xffff); \ + .word ((base) & 0xffff) ; \ + .byte (((base) >> 16) & 0xff) ; \ + .byte (SEG_PRESENT | (dpl) | SEG_NON_SYSTEM | (type)) ; \ + .byte (SEG_GRAN_4KBYTE | SEG_DB_32BIT | (((limit) >> 28) & 0xf)) ; \ + .byte (((base) >> 24) & 0xff) + +#endif /* ASM_SRC */ + +#endif diff --git a/include/cio.h b/include/cio.h new file mode 100644 index 0000000..1854f6e --- /dev/null +++ b/include/cio.h @@ -0,0 +1,287 @@ +/** +** SCCS ID: @(#)cio.h 2.7 1/22/25 +** +** @file cio.h +** +** @author Warren R. Carithers +** @authors K. Reek, Jon Coles +** +** Based on: c_io.c 1.13 (Ken Reek, Jon Coles, Warren R. Carithers) +** +** Declarations and descriptions of console I/O routines +** +** These routines provide a rudimentary capability for printing to +** the screen and reading from the keyboard. +** +** Screen output: +** There are two families of functions. The first provides a window +** that behaves in the usual manner: writes extending beyond the right +** edge of the window wrap around to the next line, the top line +** scrolls off the window to make room for new lines at the bottom. +** However, you may choose what part of the screen contains this +** scrolling window. This allows you to print some text at fixed +** locations on the screen while the rest of the screen scrolls. +** +** The second family allows for printing at fixed locations on the +** screen. No scrolling or line wrapping are done for these functions. +** It is not intended that these functions be used to write in the +** scrolling area of the screen. +** +** In both sets of functions, the (x,y) coordinates are interpreted +** as (column,row), with the upper left corner of the screen being +** (0,0) and the lower right corner being (79,24). +** +** The printf provided in both sets of functions has the same +** conversion capabilities. Format codes are of the form: +** +** %-0WC +** +** where "-", "0", and "W" are all optional: +** "-" is the left-adjust flag (default is right-adjust) +** "0" is the zero-fill flag (default is space-fill) +** "W" is a number specifying the minimum field width (default: 1 ) +** and "C" is the conversion type, which must be one of these: +** "c" print a single character +** "s" print a null-terminated string +** "d" print an integer as a decimal value +** "x" print an integer as a hexadecimal value +** "o" print an integer as a octal value +** +** Keyboard input: +** Two functions are provided: getting a single character and getting +** a newline-terminated line. A third function returns a count of +** the number of characters available for immediate reading. +** No conversions are provided (yet). +*/ + +#ifndef CIO_H_ +#define CIO_H_ + +#ifndef ASM_SRC + +// EOT indicator (control-D) +#define EOT '\04' + +/***************************************************************************** +** +** INITIALIZATION ROUTINES +** +** Initializes the I/O system. +*/ + +/** +** cio_init +** +** Initializes the I/O routines. Must be called before +** any CIO functions can be used. +** +** @param notify pointer to an input notification function, or NULL +*/ +void cio_init( void (*notify)(int) ); + +/***************************************************************************** +** +** SCROLLING OUTPUT ROUTINES +** +** Each operation begins at the current cursor position and advances +** it. If a newline is output, the reminder of that line is cleared. +** Output extending past the end of the line is wrapped. If the +** cursor is moved below the scrolling region's bottom edge, scrolling +** is delayed until the next output is produced. +*/ + +/** +** cio_setscroll +** +** This sets the scrolling region to be the area defined by the arguments. +** The remainder of the screen does not scroll and may be used to display +** data you do not want to move. By default, the scrolling region is the +** entire screen. X and Y coordinates begin at 0 in the upper left corner +** of the screen. +** +** @param min_x,min_y upper-left corner of the region +** @param max_x,max_y lower-right corner of the region +*/ +void cio_setscroll( unsigned int min_x, unsigned int min_y, + unsigned int max_x, unsigned int max_y ); + +/** +** cio_moveto +** +** Moves the cursor to the specified position. (0,0) indicates +** the upper left corner of the scrolling region. Subsequent +** output will begin at the cursor position. +** +** @param x,y desired coordinate position +*/ +void cio_moveto( unsigned int x, unsigned int y ); + +/** +** cio_putchar +** +** Prints a single character. +** +** @param c the character to be printed +*/ +void cio_putchar( unsigned int c ); + +/** +** cio_puts +** +** Prints the characters in the string up to but not including +** the terminating null byte. +** +** @param str pointer to a NUL-terminated string to be printed +*/ +void cio_puts( const char *str ); + +/** +** cio_write +** +** Prints "length" characters from the buffer. +** +** @param buf the buffer of characters +** @param length the number of characters to print +*/ +void cio_write( const char *buf, int length ); + +/** +** cio_printf +** +** Limited form of printf (see the beginning of this file for +** a list of what is implemented). +** +** @param fmt a printf-style format control string +** @param ... optional additional values to be printed +*/ +void cio_printf( char *fmt, ... ); + +/** +** cio_scroll +** +** Scroll the scrolling region up by the given number of lines. +** The output routines scroll automatically so normally you +** do not need to call this routine yourself. +** +** @param lines the number of lines to scroll +*/ +void cio_scroll( unsigned int lines ); + +/** +** cio_clearscroll +** +** Clears the entire scrolling region to blank spaces, and +** moves the cursor to (0,0). +*/ +void cio_clearscroll( void ); + +/***************************************************************************** +** +** NON-SCROLLING OUTPUT ROUTINES +** +** Coordinates are relative to the entire screen: (0,0) is the upper +** left corner. There is no line wrap or scrolling. +*/ + +/** +** cio_putchar_at +** +** Prints the given character. If a newline is printed, +** the rest of the line is cleared. If this happens to the +** left of the scrolling region, the clearing stops when the +** region is reached. If this happens inside the scrolling +** region, the clearing stops when the edge of the region +** is reached. +** +** @param x,y desired coordinate position +** @param c the character to be printed +*/ +void cio_putchar_at( unsigned int x, unsigned int y, unsigned int c ); + +/** +** cio_puts_at +** +** Prints the given string. cio_putchar_at is used to print +** the individual characters; see that description for details. +** +** @param x,y desired coordinate position +** @param str pointer to a NUL-terminated string to be printed +*/ +void cio_puts_at( unsigned int x, unsigned int y, const char *str ); + +/** +** cio_printf_at +** +** Limited form of printf (see the beginning of this file for +** a list of what is implemented). +** +** @param x,y desired coordinate position +** @param fmt a printf-style format control string +** @param ... optional additional values to be printed +*/ +void cio_printf_at( unsigned int x, unsigned int y, char *fmt, ... ); + +/** +** cio_clearscreen +** +** This function clears the entire screen, including the scrolling region. +*/ +void cio_clearscreen( void ); + +/***************************************************************************** +** +** INPUT ROUTINES +** +** When interrupts are enabled, a keyboard ISR collects keystrokes +** and saves them until the program calls for them. If the input +** queue fills, additional characters are silently discarded. +** When interrupts are not enabled, keystrokes made when no input +** routines have been ** called are lost. This can cause errors in +** the input translation because the states of the Shift and Ctrl keys +** may not be tracked accurately. If interrupts are disabled, the user +** is advised to refrain from typing anything except when the program is +** waiting for input. +*/ + +/** +** cio_getchar +** +** If the character is not immediately available, the function +** waits until the character arrives. +** +** @return the next character from the keyboard input buffer +*/ +int cio_getchar( void ); + +/** +** cio_gets +** +** This function reads a newline-terminated line from the +** keyboard. cio_getchar is used to obtain the characters; +** see that description for more details. The function +** returns when: +** a newline is entered (this is stored in the buffer) +** ctrl-D is entered (not stored in the buffer) +** the buffer becomes full. +** The buffer is null-terminated in all cases. +** +** @param buffer destination buffer for the input character sequence +** @param size the buffer length +** +** @return count of the number of characters read into the buffer +*/ +int cio_gets( char *buffer, unsigned int size ); + +/** +** cio_input_queue +** +** This function lets the program determine whether there is input +** available. This indicates whether or not a call to cio_getchar() +** would block. +** +** @return number of characters in the input queue +*/ +int cio_input_queue( void ); +#endif /* !ASM_SRC */ + +#endif diff --git a/include/clock.h b/include/clock.h new file mode 100644 index 0000000..6eae41f --- /dev/null +++ b/include/clock.h @@ -0,0 +1,55 @@ +/** +** @file clock.h +** +** @author CSCI-452 class of 20245 +** +** @brief Clock module declarations +*/ + +#ifndef CLOCK_H_ +#define CLOCK_H_ + +#include + +/* +** General (C and/or assembly) definitions +*/ + +// conversion functions for seconds, ms, and ticks +// (SEC_TO_MS is defined in defs.h) +#define MS_TO_TICKS(n) ((n)) +#define SEC_TO_TICKS(n) (MS_TO_TICKS(SEC_TO_MS(n))) +#define TICKS_TO_SEC(n) ((n) / CLOCK_FREQ) +#define TICKS_TO_SEC_ROUNDED(n) (((n)+(CLOCK_FREQ-1)) / CLOCK_FREQ) + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Types +*/ + +/* +** Globals +*/ + +// current system time +extern uint32_t system_time; + +/* +** Prototypes +*/ + +/** +** Name: clk_init +** +** Clock module initialization +*/ +void clk_init( void ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/common.h b/include/common.h new file mode 100644 index 0000000..599c492 --- /dev/null +++ b/include/common.h @@ -0,0 +1,31 @@ +/** +** @file common.h +** +** @author Warren R. Carithers +** +** @brief Common definitions for the baseline system. +** +** This header file pulls in the standard header information needed +** by all parts of the system. It is purely for our convenience. +*/ + +#ifndef COMMON_H_ +#define COMMON_H_ + +// everything needs these; they also pull in +// the kernel- or user-level defs and lib headers +#include +#include +#include +#include + +#ifdef KERNEL_SRC + +// only kernel code needs these headers +#include +#include +#include + +#endif /* KERNEL_SRC */ + +#endif diff --git a/include/compat.h b/include/compat.h new file mode 100644 index 0000000..ee62090 --- /dev/null +++ b/include/compat.h @@ -0,0 +1,131 @@ +/** +** @file compat.h +** +** @author Warren R. Carithers +** +** @brief Compatibility definitions for standard modules. +** +** These definitions are here to simplify the integration +** of some pre-written modules into the 452 baseline system. +** This is used primarily for the 'kmem' and 'sio' modules. +** +** We use CPP symbols and not actual data types for things here, +** as this means we don't need to include any other header files +** into this file. This helps get around "include loops" (e.g., +** a.h includes b.h, which includes c.h, which includes a.h) when +** there are many interdependencies between source files. +*/ + +#ifndef COMPAT_H_ +#define COMPAT_H_ + +#include +#include + +/* +** Section 1: sized integer types +** +** Internally, we use standard names for "sized" integer types for +** simplicity. If those disagree with the names used in the rest of +** the system, we take the opportunity to define our names here. +** +** To enable these, uncomment them, and place the apropriate +** existing type names in place of the '?' characters. +*/ + +// standard "sized integer" types +// #define int8_t ? +// #define uint8_t ? +// #define int16_t ? +// #define uint16_t ? +// #define int32_t ? +// #define uint32_t ? +// #define int64_t ? +// #define uint64_t ? +// #define bool_t ? + +/* +** Section 2: other types +** +** Add type definitions here as needed. +** +** Note: we do not include the PCB and Queue declarations +** here because we don't actually need them in this header +** file - we're only defining CPP macros. Whatever file +** uses these macros, however, must include the appropriate +** headers if it uses these macros. +** +** To enable these, uncomment them, and place the apropriate +** existing type names in place of the '?' characters. +*/ + +// type name for the PCB +#define PCBTYPE pcb_t + +// type name for our queue +#define QTYPE pcb_queue_t + +/* +** Section 3: interface and behavior +** +** Include #define statements here as needed to define +** the names of functions and globals used in these modules +** in terms of the names used in the rest of the baseline. +** +** To enable these, uncomment them, and place the apropriate +** existing variable or function names in place of the '?' characters. +*/ + +// string functions +#define SLENGTH strlen + +// scheduler +#define SCHED schedule + +// dispatcher +#define DISPATCH dispatch + +/* +** blocked queue for reading processes +** +** Define this if we are blocking processes which try to +** read from the SIO when no characters are available. +** Its value should be the name of the globally-visible +** queue to be used. +*/ +#define QNAME sioread + +#ifdef QNAME + +// Only define these macros if we need to be able to create and +// manage a queue of things. It is expected that these will need +// to be customized based on the names and calling sequences of +// the appropriate functions. + +// invoke the queue creation function +// examples: +// +// #define QCREATE(q) do { +// _que_create( &(q), NULL ); +// } while(0) +// +// #define QCREATE(q) // do nothing + +#define QCREATE(q) // handled elsewhere for us + +// check to see if the queue is empty +// examples: +// +// #define QEMPTY(q) queue_is_empty(q) +// #define QEMPTY(q) (quene_length(q) > 0) +#define QEMPTY(q) pcb_queue_empty(q) + +// this macro expands into code that removes a value from +// 'q' and places it into 'd' +#define QDEQUE(q,d) do { \ + assert(pcb_queue_remove( (q), (pcb_t **) &(d) ) == SUCCESS ); \ + } while(0) + +#endif /* QNAME */ + +#endif diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000..c8ddfb4 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,324 @@ +/** +** @file debug.h +** +** @author Numerous CSCI-452 classes +** +** Debugging macros and constants. +** +*/ + +#ifndef DEBUG_H_ +#define DEBUG_H_ + +// Standard system headers + +#include +#include + +// Kernel library + +#include + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** General function entry/exit announcements +*/ + +#ifdef ANNOUNCE_ENTRY +// Announce that we have entered a kernel function +// usage: ENTERING( "name" ), EXITING( "name" ) +// currently, these do not use the macro parameter, but could be +// modified to do so; instead, we use the __func__ CPP pseudo-macro +// to get the function name +#define ENTERING(n) do { cio_puts( " enter " __func__ ); } while(0) +#define EXITING(n) do { cio_puts( " exit " __func__ ); } while(0) +#else +#define ENTERING(m) // do nothing +#define EXITING(m) // do nothing +#endif + +/* +** Console messages when error conditions are noted. +*/ + +// Warning messages to the console +// m: message (condition, etc.) +#define WARNING(m) do { \ + cio_printf( "\n** %s (%s @ %d): ", __func__, __FILE__, __LINE__ ); \ + cio_puts( m ); \ + cio_putchar( '\n' ); \ + } while(0) + +// Panic messages to the console +// n: severity level +// m: message (condition, etc.) +#define PANIC(n,m) do { \ + sprint( b512, "%s (%s @ %d), %d: %s\n", \ + __func__, __FILE__, __LINE__, n, # m ); \ + kpanic( b512 ); \ + } while(0) + +/* +** Assertions are categorized by the "sanity level" being used in this +** compilation; each only triggers a fault if the sanity level is at or +** above a specific value. This allows selective enabling/disabling of +** debugging checks. +** +** The sanity level is set during compilation with the CPP macro +** "SANITY". A sanity level of 0 disables conditional assertions, +** but not the basic assert() version. +*/ + +#ifndef SANITY +// default sanity check level: check everything! +#define SANITY 9999 +#endif + +// Always-active assertions +#define assert(x) if( !(x) ) { PANIC(0,x); } + +// only provide these macros if the sanity check level is positive + +#if SANITY > 0 + +#define assert1(x) if( SANITY >= 1 && !(x) ) { PANIC(1,x); } +#define assert2(x) if( SANITY >= 2 && !(x) ) { PANIC(2,x); } +#define assert3(x) if( SANITY >= 3 && !(x) ) { PANIC(3,x); } +#define assert4(x) if( SANITY >= 4 && !(x) ) { PANIC(4,x); } +// arbitrary sanity level +#define assertN(n,x) if( SANITY >= (n) && !(x) ) { PANIC(n,x); } + +#else + +#define assert1(x) // do nothing +#define assert2(x) // do nothing +#define assert3(x) // do nothing +#define assert4(x) // do nothing +#define assertN(n,x) // do nothing + +#endif /* SANITY > 0 */ + +/* +** Tracing options are enabled by defining one or more of the T_ +** macros described in the Makefile. +** +** To add a tracing option: +** +** 1) Pick a short name for it (e.g., "PCB", "VM", ...) +** 2) At the end of this list, add code like this, with "name" +** replaced by your short name, and "nnnnnnnn" replaced by a +** unique bit that will designate this tracing option: +** +** #ifdef T_name +** #define TRname 0xnnnnnnnn +** #else +** #define TRname 0 +** #endif +** +** Use the next bit position following the one in last list entry. +** 3) Add this to the end of the "TRACE" macro definition: +** +** | TRname +** +** 4) In the list of "TRACING_*" macros, add one for your option +** (using a name that might be more descriptive) in the 'then' clause: +** +** #define TRACING_bettername ((TRACE & TRname) != 0) +** +** 5) Also add a "null" version in the 'else' clause: +** +** #define TRACING_bettername 0 +** +** 6) Maybe add your T_name choice to the Makefile with an explanation +** on the off chance you want anyone else to be able to understand +** what it's used for. :-) +** +** We're making CPP work for its pay with this file. +*/ + +// 2^0 bit +#ifdef T_PCB +#define TRPCB 0x00000001 +#else +#define TRPCB 0 +#endif + +#ifdef T_VM +#define TRVM 0x00000002 +#else +#define TRVM 0 +#endif + +#ifdef T_QUE +#define TRQUEUE 0x00000004 +#else +#define TRQUEUE 0 +#endif + +#ifdef T_SCH +#define TRSCHED 0x00000008 +#else +#define TRSCHED 0 +#endif + +// 2^4 bit +#ifdef T_DSP +#define TRDISP 0x00000010 +#else +#define TRDISP 0 +#endif + +#ifdef T_SCALL +#define TRSYSCALLS 0x00000020 +#else +#define TRSYSCALLS 0 +#endif + +#ifdef T_SRET +#define TRSYSRETS 0x00000040 +#else +#define TRSYSRETS 0 +#endif + +#ifdef T_EXIT +#define TREXIT 0x00000080 +#else +#define TREXIT 0 +#endif + +// 2^8 bit +#ifdef T_INIT +#define TRINIT 0x00000100 +#else +#define TRINIT 0 +#endif + +#ifdef T_KM +#define TRKMEM 0x00000200 +#else +#define TRKMEM 0 +#endif + +#ifdef T_KMFR +#define TRKMEM_F 0x00000400 +#else +#define TRKMEM_F 0 +#endif + +#ifdef T_KMIN +#define TRKMEM_I 0x00000800 +#else +#define TRKMEM_I 0 +#endif + +// 2^12 bit +#ifdef T_FORK +#define TRFORK 0x00001000 +#else +#define TRFORK 0 +#endif + +#ifdef T_EXEC +#define TREXEC 0x00002000 +#else +#define TREXEC 0 +#endif + +#ifdef T_SIO +#define TRSIO_STAT 0x00004000 +#else +#define TRSIO_STAT 0 +#endif + +#ifdef T_SIOR +#define TRSIO_RD 0x00008000 +#else +#define TRSIO_RD 0 +#endif + +// 2^16 bit +#ifdef T_SIOW +#define TRSIO_WR 0x00010000 +#else +#define TRSIO_WR 0 +#endif + +#ifdef T_USER +#define TRUSER 0x00020000 +#else +#define TRUSER 0 +#endif + +#ifdef T_ELF +#define TRELF 0x00040000 +#else +#define TRELF 0 +#endif + +// 13 bits remaining for tracing options +// next available bit: 0x00080000 + +#define TRACE (TRDISP | TREXIT | TRINIT | TRKMEM | TRKMEM_F | TRKMEM_I | TRPCB | TRQUEUE | TRSCHED | TREXEC | TRSIO_RD | TRSIO_STAT | TRSIO_WR | TRFORK | TRVM | TRSYSCALLS | TRSYSRETS | TRUSER | TRELF) + +#if TRACE > 0 + +// compile-time expressions for testing trace options +// usage: #if TRACING_thing +#define TRACING_PCB ((TRACE & TRPCB) != 0) +#define TRACING_VM ((TRACE & TRVM) != 0) +#define TRACING_QUEUE ((TRACE & TRQUEUE) != 0) +#define TRACING_SCHED ((TRACE & TRSCHED) != 0) +#define TRACING_SYSCALLS ((TRACE & TRSYSCALLS) != 0) +#define TRACING_SYSRETS ((TRACE & TRSYSRETS) != 0) +#define TRACING_EXIT ((TRACE & TREXIT) != 0) +#define TRACING_DISPATCH ((TRACE & TRDISPATCH) != 0) +#define TRACING_INIT ((TRACE & TRINIT) != 0) +#define TRACING_KMEM ((TRACE & TRKMEM) != 0) +#define TRACING_KMEM_FREELIST ((TRACE & TRKMEM_F) != 0) +#define TRACING_KMEM_INIT ((TRACE & TRKMEM_I) != 0) +#define TRACING_SPAWN ((TRACE & TRSPAWN) != 0) +#define TRACING_SIO_STAT ((TRACE & TRSIO_STAT) != 0) +#define TRACING_SIO_ISR ((TRACE & TRSIO_ISR) != 0) +#define TRACING_SIO_RD ((TRACE & TRSIO_RD) != 0) +#define TRACING_SIO_WR ((TRACE & TRSIO_WR) != 0) +#define TRACING_USER ((TRACE & TRUSER) != 0) +#define TRACING_ELF ((TRACE & TRELF) != 0) + +#define TRACING_SOMETHING (TRACE != 0) + +#else + +// TRACE == 0, so just define these all as "false" + +#define TRACING_PCB 0 +#define TRACING_STACK 0 +#define TRACING_QUEUE 0 +#define TRACING_SCHED 0 +#define TRACING_SYSCALLS 0 +#define TRACING_SYSRET 0 +#define TRACING_EXIT 0 +#define TRACING_DISPATCH 0 +#define TRACING_INIT 0 +#define TRACING_KMEM 0 +#define TRACING_KMEM_FREELIST 0 +#define TRACING_KMEM_INIT 0 +#define TRACING_SPAWN 0 +#define TRACING_SI_STAT 0 +#define TRACING_SIO_ISR 0 +#define TRACING_SIO_RD 0 +#define TRACING_SIO_WR 0 +#define TRACING_USER 0 +#define TRACING_ELF 0 + +#define TRACING_SOMETHING 0 + +#endif /* TRACE */ + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/defs.h b/include/defs.h new file mode 100644 index 0000000..0280c47 --- /dev/null +++ b/include/defs.h @@ -0,0 +1,129 @@ +/** +** @file defs.h +** +** @author Warren R. Carithers +** +** @brief Common definitions. +** +** This header file defines things which are neede by all +** parts of the system (OS and user levels). +** +** Things which are kernel-specific go in the kdefs.h file; +** things which are user-specific go in the udefs.h file. +** The correct one of these will be automatically included +** at the end of this file. +*/ + +#ifndef DEFS_H_ +#define DEFS_H_ + +/* +** General (C and/or assembly) definitions +** +** This section of the header file contains definitions that can be +** used in either C or assembly-language source code. +*/ + +// NULL pointer value +// +// we define this the traditional way so that +// it's usable from both C and assembly + +#define NULL 0 + +// predefined i/o channels + +#define CHAN_CIO 0 +#define CHAN_SIO 1 + +// maximum allowable number of command-line arguments +#define MAX_ARGS 10 + +// sizes of various things +#define NUM_1KB 0x00000400 // 2^10 +#define NUM_4KB 0x00001000 // 2^12 +#define NUM_1MB 0x00100000 // 2^20 +#define NUM_4MB 0x00400000 // 2^22 +#define NUM_1GB 0x40000000 // 2^30 +#define NUM_2GB 0x80000000 // 2^31 +#define NUM_3GB 0xc0000000 + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +** +** Anything that should not be visible to something other than +** the C compiler should be put here. +*/ + +/* +** System error codes +** +** These can be returned to both system functions +** and to user system calls. +*/ + // success! +#define SUCCESS (0) +# define E_SUCCESS SUCCESS + // generic "something went wrong" +#define E_FAILURE (-1) + // specific failure reasons +#define E_BAD_PARAM (-2) +#define E_BAD_CHAN (-3) +#define E_NO_CHILDREN (-4) +#define E_NO_MEMORY (-5) +#define E_NOT_FOUND (-6) +#define E_NO_PROCS (-7) + +/* +** These error codes are internal to the OS. +*/ +#define E_EMPTY_QUEUE (-100) +#define E_NO_PCBS (-101) +#define E_NO_PTE (-102) +#define E_LOAD_LIMIT (-103) + +// exit status values +#define EXIT_SUCCESS (0) +#define EXIT_FAILURE (-1) +#define EXIT_KILLED (-101) +#define EXIT_BAD_SYSCALL (-102) + +/* +** Process priority values +*/ +enum priority_e { + PRIO_HIGH, PRIO_STD, PRIO_LOW, PRIO_DEFERRED + // sentinel + , N_PRIOS +}; + +// halves of various data sizes + +#define UI16_UPPER 0xff00 +#define UI16_LOWER 0x00ff + +#define UI32_UPPER 0xffff0000 +#define UI32_LOWER 0x0000ffff + +#define UI64_UPPER 0xffffffff00000000LL +#define UI64_LOWER 0x00000000ffffffffLL + +// Simple conversion pseudo-functions usable by everyone + +// convert seconds to ms +#define SEC_TO_MS(n) ((n) * 1000) + +#endif /* !ASM_SRC */ + +/* +** Level-specific definitions +*/ +#ifdef KERNEL_SRC +#include +#else +#include +#endif /* KERNEL_SRC */ + +#endif diff --git a/include/elf.h b/include/elf.h new file mode 100644 index 0000000..a43e5c3 --- /dev/null +++ b/include/elf.h @@ -0,0 +1,235 @@ +/** +** @file elf.h +** +** @author Warren R. Carithers +** +** @brief ELF format declarations +*/ + +#ifndef ELF_H_ +#define ELF_H_ + +#include + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +// ELF data types (TIS ELF Spec v1.2, May 1995 +typedef uint32_t e32_a; // 32-bit unsigned address +typedef uint16_t e32_h; // 16-bit unsigned "medium" integer +typedef uint32_t e32_o; // 32-bit unsigned offset +typedef int32_t e32_sw; // 32-bit signed "large" integer +typedef uint32_t e32_w; // 32-bit unsigned "large" integer +typedef uint8_t e32_si; // 8-bit unsigned "small" integer + +// ELF magic number - first four bytes +#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little-endian order +#define EI_NIDENT 16 + +union elfident_u { + uint8_t bytes[EI_NIDENT]; // array of 16 bytes + struct { + uint32_t magic; // magic number + uint8_t class; // file class + uint8_t data; // data encoding + uint8_t version; // file version + uint8_t osabi; // OS ABI identification + uint8_t abivers; // ABI version + uint8_t pad[7]; // padding to 16 bytes + } f; +}; + +// indices for byte fields in the ident array +#define EI_MAGIC 0 +# define EI_MAG0 EI_MAGIC +# define EI_MAG1 1 +# define EI_MAG2 2 +# define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_ABIVERSION 8 + +// ELF classes +#define ELF_CLASS_NONE 0 +#define ELF_CLASS_32 1 // 32-bit objects +#define ELF_CLASS_64 2 // 64-bit objects + +// ELF data encoding +#define ELF_DATA_NONE 0 // invalid data encoding +#define ELF_DATA_2LSB 1 // two's complement little-endian +#define ELF_DATA_2MSB 2 // two's complement big-endian + +// ELF versions +#define ELF_VERSION__NONE 0 // invalid version +# define EV_NONE ELF_VERSION_NONE +#define ELF_VERSION__CURRENT 1 // current version +# define EV_CURRENT ELF_VERSION_CURRENT + +// ELF header +// +// field names are from the TIS ELF Spec v1.2, May 1995 +typedef struct elfhdr_s { + union elfident_u e_ident; // file identification + e32_h e_type; // file type + e32_h e_machine; // required architecture + e32_w e_version; // object file version + e32_a e_entry; // entry point (VA) + e32_o e_phoff; // offset to program header table (PHT) + e32_o e_shoff; // offset to section header table (SHT) + e32_w e_flags; // processor-specific flags + e32_h e_ehsize; // ELF header size (bytes) + e32_h e_phentsize; // size of one PHT entry (bytes) + e32_h e_phnum; // number of PHT entries + e32_h e_shentsize; // size of one SHT entry (bytes) + e32_h e_shnum; // number of SHT entries + e32_h e_shstrndx; // SHT index of the sect. name string table +} elfhdr_t; + +#define SZ_ELFHDR sizeof(elfhdr_t) + +// field values +// e_type +#define ET_NONE 0 // no file type +#define ET_REL 1 // relocatable file +#define ET_EXEC 2 // executable file +#define ET_DYN 3 // shared object file +#define ET_CORE 4 // core file +#define ET_LO_OS 0xfe00 // processor-specific +#define ET_HI_OS 0xfeff // processor-specific +#define ET_LO_CP 0xff00 // processor-specific +#define ET_HI_CP 0xffff // processor-specific + +// e_machine +#define EM_NONE 0x00 // no machine type +#define EM_M32 0x01 // AT&T WE 32100 +#define EM_SPARC 0x02 // SUN SPARC +#define EM_386 0x03 // Intel Architecture +#define EM_68K 0x04 // Motorola 68000 +#define EM_88K 0x05 // Motorola 88000 +#define EM_IAMCU 0x06 // Intel MCU +#define EM_860 0x07 // Intel 80860 +#define EM_MIPS 0x08 // MIPS RS3000 Big-Endian +#define EM_S370 0x09 // IBM System/370 +#define EM_MIPS_RS3_LE 0x0a // MIPS RS3000 Big-Endian +#define EM_SPARC32PLLUS 0x12 // Sun "v8plus" +#define EM_PPC 0x14 // IBM PowerPC +#define EM_PPC64 0x15 // IBM PowerPC 64-bit +#define EM_S390 0x16 // IBM System/390 +#define EM_ARM 0x28 // ARM up to V7/AArch32 +#define EM_SPARCV9 0x2b // SPARC V9 64-bit +#define EM_IA_64 0x32 // Intel Itanium (Merced) +#define EM_MIPS_X 0x32 // Stanford MIPS-X +#define EM_X86_64 0x3E // AMD x86-64 (Intel64) +#define EM_PDP11 0x40 // DEC PDP-11 +#define EM_VAX 0x4b // DEC VAX +#define EM_AARCH64 0xb7 // ARM AArch64 +#define EM_Z80 0xec // Zilog Z-80 +#define EM_AMDGPU 0xf0 // AMD GPU +#define EM_RISCV 0xf3 // RISC-V +#define EM_BPF 0xf7 // Berkeley Packet Filter + +// ELF section header +// +// field names are from the TIS ELF Spec v1.2, May 1995 +typedef struct shdr_s { + e32_w sh_name; // section name (index into string table) + e32_w sh_type; // section contents/semantics + e32_w sh_flags; // attribute flag bits + e32_a sh_addr; // 0, or load point of this section in memory + e32_o sh_offset; // byte offset within the file + e32_w sh_size; // section size in bytes + e32_w sh_link; // section header index table link + e32_w sh_info; // "extra information" + e32_w sh_addralign; // required alignment + e32_w sh_entsize; // 0, or size of each entry in the section +} elfsecthdr_t; + +#define SZ_ELFSECTHDR sizeof(elfsecthdr_t) + +// sh_name +#define SHN_UNDEF 0 + +// sh_type +#define SHT_NULL 0x00 +#define SHT_PROGBITS 0x01 +#define SHT_SYMTAB 0x02 +#define SHT_STRTAB 0x03 +#define SHT_RELA 0x04 +#define SHT_HASH 0x05 +#define SHT_DYNAMIC 0x06 +#define SHT_NOTE 0x07 +#define SHT_NOBITS 0x08 +#define SHT_REL 0x09 +#define SHT_SHLIB 0x0a +#define SHT_DYNSYM 0x0b +#define SHT_LO_CP 0x70000000 +#define SHT_HI_CP 0x7fffffff +#define SHT_LO_US 0x80000000 +#define SHT_HI_US 0x8fffffff + +// sh_flags +#define SHF_WRITE 0x001 +#define SHF_ALLOC 0x002 +#define SHF_EXECINSTR 0x004 +#define SHF_MERGE 0x010 +#define SHF_STRINGS 0x020 +#define SHF_INFO_LINK 0x040 +#define SHF_LINK_ORDER 0x080 +#define SHF_OS_NONCON 0x100 +#define SHF_GROUP 0x200 +#define SHF_TLS 0x400 +#define SHF_MASKOS 0x0ff00000 +#define SHF_MASKPROC 0xf0000000 + +// ELF program header +// +// field names are from the TIS ELF Spec v1.2, May 1995 +typedef struct phdr_s { + e32_w p_type; // type of segment + e32_o p_offset; // byte offset in file + e32_a p_va; // load point in memory (virtual address) + e32_a p_pa; // load point in memory (physical address) + e32_w p_filesz; // number of bytes in this file + e32_w p_memsz; // number of bytes in memory + e32_w p_flags; // attribute flag bits + e32_w p_align; // required alignment +} elfproghdr_t; + +#define SZ_ELFPROGHDR sizeof(elfproghdr_t) + +// p_type +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 +#define PT_LO_OS 0x70000000 +#define PT_HI_OS 0x7fffffff +#define PT_LO_CP 0x70000000 +#define PT_HI_CP 0x7fffffff + +// p_flags +#define PF_E 0x1 +#define PF_W 0x2 +#define PF_R 0x4 +#define PF_MASKPROC 0xf0000000 + +/* +** Globals +*/ + +/* +** Prototypes +*/ + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/kdefs.h b/include/kdefs.h new file mode 100644 index 0000000..f9fe853 --- /dev/null +++ b/include/kdefs.h @@ -0,0 +1,146 @@ +/** +** @file kdefs.h +** +** @author CSCI-452 class of 20245 +** +** @brief Kernel-only declarations. +*/ + +#ifndef KDEFS_H_ +#define KDEFS_H_ + +// debugging macros +#include + +/* +** General (C and/or assembly) definitions +*/ + +// page sizes +#define SZ_PAGE NUM_4KB +#define SZ_BIGPAGE NUM_4MB + +// kernel stack size (bytes) +#define N_KSTKPAGES 1 +#define SZ_KSTACK (N_KSTKPAGES * SZ_PAGE) + +// user stack size +#define N_USTKPAGES 2 +#define SZ_USTACK (N_USTKPAGES * SZ_PAGE) + +// declarations for modulus checking of (e.g.) sizes and addresses + +#define MOD4_BITS 0x00000003 +#define MOD4_MASK 0xfffffffc +#define MOD4_INC 0x00000004 +#define MOD4_SHIFT 2 + +#define MOD16_BITS 0x0000000f +#define MOD16_MASK 0xfffffff0 +#define MOD16_INC 0x00000010 +#define MOD16_SHIFT 4 + +#define MOD1K_BITS 0x000003ff +#define MOD1K_MASK 0xfffffc00 +#define MOD1K_INC 0x00000400 +#define MOD1K_SHIFT 10 + +#define MOD4K_BITS 0x00000fff +#define MOD4K_MASK 0xfffff000 +#define MOD4K_INC 0x00001000 +#define MOD4K_SHIFT 12 + +#define MOD1M_BITS 0x000fffff +#define MOD1M_MASK 0xfff00000 +#define MOD1M_INC 0x00100000 +#define MOD1M_SHIFT 20 + +#define MOD1G_BITS 0x3fffffff +#define MOD1G_MASK 0xc0000000 +#define MOD1G_INC 0x40000000 +#define MOD1G_SHIFT 30 + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +// unit conversion macros +#define B_TO_KB(x) (((uint_t)(x))>>10) +#define B_TO_MB(x) (((uint_t)(x))>>20) +#define B_TO_GB(x) (((uint_t)(x))>>30) + +#define KB_TO_B(x) (((uint_t)(x))<<10) +#define KB_TO_MB(x) (((uint_t)(x))>>10) +#define KB_TO_GB(x) (((uint_t)(x))>>20) + +#define MB_TO_B(x) (((uint_t)(x))<<20) +#define MB_TO_KB(x) (((uint_t)(x))<<10) +#define MB_TO_GB(x) (((uint_t)(x))>>10) + +#define GB_TO_B(x) (((uint_t)(x))<<30) +#define GB_TO_KB(x) (((uint_t)(x))<<20) +#define GB_TO_MB(x) (((uint_t)(x))<<10) + +// potetially useful compiler attributes +#define ALIGN(x) __attribute__((__aligned__(x))) +#define PACKED __attribute__((__packed__)) + +/* +** Utility macros +*/ + +// +// macros to clear data structures +// +// these are usable for clearing single-valued data items (e.g., +// a PCB, etc.) +#define CLEAR(v) memclr( &v, sizeof(v) ) +#define CLEAR_PTR(p) memclr( p, sizeof(*p) ) + +// +// macros for access registers and system call arguments +// + +// REG(pcb,x) -- access a specific register in a process context +#define REG(pcb,x) ((pcb)->context->x) + +// RET(pcb) -- access return value register in a process context +#define RET(pcb) ((pcb)->context->eax) + +// ARG(pcb,n) -- access argument #n from the indicated process +// +// ARG(pcb,0) --> return address +// ARG(pcb,1) --> first parameter +// ARG(pcb,2) --> second parameter +// etc. +// +// ASSUMES THE STANDARD 32-BIT ABI, WITH PARAMETERS PUSHED ONTO THE +// STACK. IF THE PARAMETER PASSING MECHANISM CHANGES, SO MUST THIS! +#define ARG(pcb,n) ( ( (uint32_t *) (((pcb)->context) + 1) ) [(n)] ) + +/* +** Types +*/ + +/* +** Globals +*/ + +// general-purpose character buffer +extern char b256[256]; + +// buffer for use by PANIC() macro +extern char b512[512]; + +// kernel stack +extern uint8_t kstack[SZ_KSTACK]; + +/* +** Prototypes +*/ + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/klib.h b/include/klib.h new file mode 100644 index 0000000..c1d270c --- /dev/null +++ b/include/klib.h @@ -0,0 +1,57 @@ +/* +** @file klib.h +** +** @author Warren R. Carithers +** +** Additional support functions for the kernel. +*/ + +#ifndef KLIB_H_ +#define KLIB_H_ + +#include + +#ifndef ASM_SRC + +#include + +/** +** Name: put_char_or_code( ch ) +** +** Description: Prints a character on the console, unless it +** is a non-printing character, in which case its hex code +** is printed +** +** @param ch The character to be printed +*/ +void put_char_or_code( int ch ); + +/** +** Name: backtrace +** +** Perform a simple stack backtrace. Could be augmented to use the +** symbol table to print function/variable names, etc., if so desired. +** +** @param ebp Initial EBP to use +** @param args Number of function argument values to print +*/ +void backtrace( uint32_t *ebp, uint_t args ); + +/** +** Name: kpanic +** +** Kernel-level panic routine +** +** usage: kpanic( msg ) +** +** Prefix routine for panic() - can be expanded to do other things +** (e.g., printing a stack traceback) +** +** @param msg[in] String containing a relevant message to be printed, +** or NULL +*/ +void kpanic( const char *msg ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/kmem.h b/include/kmem.h new file mode 100644 index 0000000..5a98765 --- /dev/null +++ b/include/kmem.h @@ -0,0 +1,138 @@ +/** +** @file kmem.h +** +** @author Warren R. Carithers +** @author Kenneth Reek +** @author 4003-506 class of 20013 +** +** @brief Support for dynamic memory allocation within the OS. +** +** This is a basic page allocator. Each allocation request returns +** a pointer to a single 4096-byte page of memory. +** +** The module also supports subddivision of pages into "slices", +** each of which is 1KB (i.e., 1/4 of a page). +*/ + +#ifndef KMEM_H_ +#define KMEM_H_ + +#define KERNEL_SRC + +// standard types etc. +#include + +/* +** General (C and/or assembly) definitions +*/ + +// Slab and slice sizes, in bytes + +#define SZ_SLAB SZ_PAGE +#define SZ_SLICE (SZ_SLAB >> 2) + +// memory limits +// +// these determine the range of memory addresses the kmem +// module will manage +// +// we won't map any memory below 1MB or above 1GB +#define KM_LOW_CUTOFF NUM_1MB +#define KM_HIGH_CUTOFF NUM_1GB + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Types +*/ + +/* +** Globals +*/ + +/* +** Prototypes +*/ + +/** +** Name: km_init +** +** Find what memory is present on the system and +** construct the list of free memory blocks. +** +** Dependencies: +** Must be called before any other init routine that uses +** dynamic storage is called. +*/ +void km_init( void ); + +/** +** Name: km_dump +** +** Dump information about the free lists to the console. By default, +** prints only the list sizes; if 'addrs' is true, also dumps the list +** of page addresses; if 'all' is also true, dumps page addresses and +** slice addresses. +** +** @param addrs Also dump page addresses +** @param both Also dump slice addresses +*/ +void km_dump( bool_t addrs, bool_t both ); + +/* +** Functions that manipulate free memory blocks. +*/ + +/** +** Name: km_page_alloc +** +** Allocate a page of memory from the free list. +** +** @return a pointer to the beginning of the allocated page, +** or NULL if no memory is available +*/ +void *km_page_alloc( void ); + +/** +** Name: km_page_free +** +** Returns a memory block to the list of available blocks, +** combining it with adjacent blocks if they're present. +** +** CRITICAL ASSUMPTION: multi-page blocks will be freed one page +** at a time! +** +** @param[in] block Pointer to the page to be returned to the free list +*/ +void km_page_free( void *block ); + +/** +** Name: km_slice_alloc +** +** Dynamically allocates a slice (1/4 of a page). If no +** memory is available, we return NULL (unless ALLOC_FAIL_PANIC +** was defined, in which case we panic). +** +** @return a pointer to the allocated slice +*/ +void *km_slice_alloc( void ); + +/** +** Name: km_slice_free +** +** Returns a slice to the list of available slices. +** +** We make no attempt to merge slices, as they are independent +** blocks of memory (unlike pages). +** +** @param[in] block Pointer to the slice (1/4 page) to be freed +*/ +void km_slice_free( void *block ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/lib.h b/include/lib.h new file mode 100644 index 0000000..bd19111 --- /dev/null +++ b/include/lib.h @@ -0,0 +1,287 @@ +/** +** @file lib.h +** +** @author Numerous CSCI-452 classes +** +** @brief C declarations of common library functions +** +** These are callable from either kernel or user code. Care should be taken +** that user code is linked against these separately from kernel code, to +** ensure separation of the address spaces. +*/ + +#ifndef LIB_H_ +#define LIB_H_ + +#ifndef ASM_SRC + +#include + +/* +********************************************** +** MEMORY MANIPULATION FUNCTIONS +********************************************** +*/ + +/** +** memset(buf,len,value) +** +** initialize all bytes of a block of memory to a specific value +** +** @param buf The buffer to initialize +** @param len Buffer size (in bytes) +** @param value Initialization value +*/ +void memset( void *buf, register uint32_t len, register uint32_t value ); + +/** +** memclr(buf,len) +** +** Initialize all bytes of a block of memory to zero +** +** @param buf The buffer to initialize +** @param len Buffer size (in bytes) +*/ +void memclr( void *buf, register uint32_t len ); + +/** +** memcpy(dst,src,len) +** +** Copy a block from one place to another +** +** May not correctly deal with overlapping buffers +** +** @param dst Destination buffer +** @param src Source buffer +** @param len Buffer size (in bytes) +*/ +void memcpy( void *dst, register const void *src, register uint32_t len ); + +/* +********************************************** +** STRING MANIPULATION FUNCTIONS +********************************************** +*/ + +/** +** str2int(str,base) - convert a string to a number in the specified base +** +** @param str The string to examine +** @param base The radix to use in the conversion +** +** @return The converted integer +*/ +int str2int( register const char *str, register int base ); + +/** +** strlen(str) - return length of a NUL-terminated string +** +** @param str The string to examine +** +** @return The length of the string, or 0 +*/ +uint32_t strlen( register const char *str ); + +/** +** strcmp(s1,s2) - compare two NUL-terminated strings +** +** @param s1 The first source string +** @param s2 The second source string +** +** @return negative if s1 < s2, zero if equal, and positive if s1 > s2 +*/ +int strcmp( register const char *s1, register const char *s2 ); + +/** +** strcpy(dst,src) - copy a NUL-terminated string +** +** @param dst The destination buffer +** @param src The source buffer +** +** @return The dst parameter +** +** NOTE: assumes dst is large enough to hold the copied string +*/ +char *strcpy( register char *dst, register const char *src ); + +/** +** strcat(dst,src) - append one string to another +** +** @param dst The destination buffer +** @param src The source buffer +** +** @return The dst parameter +** +** NOTE: assumes dst is large enough to hold the resulting string +*/ +char *strcat( register char *dst, register const char *src ); + +/** +** pad(dst,extra,padchar) - generate a padding string +** +** @param dst Pointer to where the padding should begin +** @param extra How many padding bytes to add +** @param padchar What character to pad with +** +** @return Pointer to the first byte after the padding +** +** NOTE: does NOT NUL-terminate the buffer +*/ +char *pad( char *dst, int extra, int padchar ); + +/** +** padstr(dst,str,len,width,leftadjust,padchar - add padding characters +** to a string +** +** @param dst The destination buffer +** @param str The string to be padded +** @param len The string length, or -1 +** @param width The desired final length of the string +** @param leftadjust Should the string be left-justified? +** @param padchar What character to pad with +** +** @return Pointer to the first byte after the padded string +** +** NOTE: does NOT NUL-terminate the buffer +*/ +char *padstr( char *dst, char *str, int len, int width, + int leftadjust, int padchar ); + +/** +** sprint(dst,fmt,...) - formatted output into a string buffer +** +** @param dst The string buffer +** @param fmt Format string +** +** The format string parameter is followed by zero or more additional +** parameters which are interpreted according to the format string. +** +** NOTE: assumes the buffer is large enough to hold the result string +** +** NOTE: relies heavily on the x86 parameter passing convention +** (parameters are pushed onto the stack in reverse order as +** 32-bit values). +*/ +void sprint( char *dst, char *fmt, ... ); + +/* +********************************************** +** CONVERSION FUNCTIONS +********************************************** +*/ + +/** +** cvtuns0(buf,value) - local support routine for cvtuns() +** +** Convert a 32-bit unsigned value into a NUL-terminated character string +** +** @param buf Result buffer +** @param value Value to be converted +** +** @return Pointer to the first unused byte in the buffer +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +char *cvtuns0( char *buf, uint32_t value ); + +/** +** cvtuns(buf,value) +** +** Convert a 32-bit unsigned value into a NUL-terminated character string +** +** @param buf Result buffer +** @param value Value to be converted +** +** @return Length of the resulting buffer +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +int cvtuns( char *buf, uint32_t value ); + +/** +** cvtdec0(buf,value) - local support routine for cvtdec() +** +** convert a 32-bit unsigned integer into a NUL-terminated character string +** +** @param buf Destination buffer +** @param value Value to convert +** +** @return The number of characters placed into the buffer +** (not including the NUL) +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +char *cvtdec0( char *buf, int value ); + +/** +** cvtdec(buf,value) +** +** convert a 32-bit signed value into a NUL-terminated character string +** +** @param buf Destination buffer +** @param value Value to convert +** +** @return The number of characters placed into the buffer +** (not including the NUL) +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +int cvtdec( char *buf, int32_t value ); + +/** +** cvthex(buf,value) +** +** convert a 32-bit unsigned value into a mininal-length (up to +** 8-character) NUL-terminated character string +** +** @param buf Destination buffer +** @param value Value to convert +** +** @return The number of characters placed into the buffer +** (not including the NUL) +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +int cvthex( char *buf, uint32_t value ); + +/** +** cvtoct(buf,value) +** +** convert a 32-bit unsigned value into a mininal-length (up to +** 11-character) NUL-terminated character string +** +** @param buf Destination buffer +** @param value Value to convert +** +** @return The number of characters placed into the buffer +** (not including the NUL) +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +int cvtoct( char *buf, uint32_t value ); + +/** +** bound(min,value,max) +** +** This function confines an argument within specified bounds. +** +** @param min Lower bound +** @param value Value to be constrained +** @param max Upper bound +** +** @return The constrained value +*/ +uint32_t bound( uint32_t min, uint32_t value, uint32_t max ); + +#endif /* !ASM_SRC */ + +/* +** Finally, pull in the level-specific library headers +*/ +#ifdef KERNEL_SRC +#include +#else +#include +#endif /* KERNEL_SRC */ + +#endif diff --git a/include/list.h b/include/list.h new file mode 100644 index 0000000..28c2377 --- /dev/null +++ b/include/list.h @@ -0,0 +1,68 @@ +/** +** @file list.h +** +** @author Warren R. Carithers +** +** @brief Support for a basic linked list data type. +** +** This module provides a very basic linked list data structure. +** A list can contain anything that has a pointer field in the first +** four bytes; these routines assume those bytes contain a pointer to +** the following entry in the list, whatever that may be. +*/ + +#ifndef LIST_H_ +#define LIST_H_ + +#define KERNEL_SRC + +// standard types etc. +#include + +/* +** General (C and/or assembly) definitions +*/ + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Data types +*/ + +// The list structure +typedef struct list_s { + struct list_s *next; // link to the successor +} list_t; + +/* +** Prototypes +*/ + +/** +** Name: list_add +** +** Add the supplied data to the beginning of the specified list. +** +** @param[in,out] list The address of a list_t variable +** @param[in] data The data to prepend to the list +*/ +void list_add( list_t *list, void *data ); + +/** +** Name: list_remove +** +** Remove the first entry from a linked list. +** +** @param[in,out] list The address of a list_t variable +** +** @return a pointer to the removed data, or NULL if the list was empty +*/ +void *list_remove( list_t *list ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/params.h b/include/params.h new file mode 100644 index 0000000..52eb81d --- /dev/null +++ b/include/params.h @@ -0,0 +1,31 @@ +/** +** @file params.h +** +** @author CSCI-452 class of 20245 +** +** @brief System configuration settings +** +** This header file contains many of the "easily tunable" system +** settings, such as clock rate, number of simultaneous user +** processes, etc. This provides a sort of "one-stop shop" for +** things that might be tweaked frequently. +*/ + +#ifndef PARAMS_H_ +#define PARAMS_H_ + +/* +** General (C and/or assembly) definitions +*/ + +// Upper bound on the number of simultaneous user-level +// processes in the system (completely arbitrary) + +#define N_PROCS 25 + +// Clock frequency (Hz) + +#define CLOCK_FREQ 1000 +#define TICKS_PER_MS 1 + +#endif diff --git a/include/procs.h b/include/procs.h new file mode 100644 index 0000000..9db4ac8 --- /dev/null +++ b/include/procs.h @@ -0,0 +1,452 @@ +/* +** @file procs.h +** +** @author CSCI-452 class of 20245 +** +** @brief Process-related declarations +*/ + +#ifndef PROCS_H_ +#define PROCS_H_ + +#include + +/* +** General (C and/or assembly) definitions +*/ + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Types +*/ + +/* +** Process states +*/ +enum state_e { + // pre-viable + STATE_UNUSED = 0, STATE_NEW, + // runnable + STATE_READY, STATE_RUNNING, + // runnable, but waiting for some event + STATE_SLEEPING, STATE_BLOCKED, STATE_WAITING, + // no longer runnable + STATE_KILLED, STATE_ZOMBIE + // sentinel value + , N_STATES +}; + +// these may be handy for checking general conditions of processes +// they depend on the order of the state names in the enum! +#define FIRST_VIABLE STATE_READY +#define FIRST_BLOCKED STATE_SLEEPING +#define LAST_VIABLE STATE_WAITING + +/* +** Process priorities are defined in +*/ + +/* +** Quantum lengths - values are number of clock ticks +*/ +enum quantum_e { + QUANTUM_SHORT = 1, + QUANTUM_STANDARD = 3, + QUANTUM_LONG = 5 +}; + +/* +** PID-related definitions +*/ +#define PID_INIT 1 +#define FIRST_USER_PID 2 + +/* +** Process context structure +** +** NOTE: the order of data members here depends on the +** register save code in isr_stubs.S!!!! +** +** This will be at the top of the user stack when we enter +** an ISR. In the case of a system call, it will be followed +** by the return address and the system call parameters. +*/ + +typedef struct context_s { + uint32_t ss; // pushed by isr_save + uint32_t gs; + uint32_t fs; + uint32_t es; + uint32_t ds; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t vector; + uint32_t code; // pushed by isr_save or the hardware + uint32_t eip; // pushed by the hardware + uint32_t cs; + uint32_t eflags; +} context_t; + +#define SZ_CONTEXT sizeof(context_t) + +/* +** program section information for user processes +*/ + +typedef struct section_s { + uint_t length; // length, in some units + uint_t addr; // location, in some units +} section_t; + +// note: these correspond to the PT_LOAD sections found in +// an ELF file, not necessarily to text/data/bss +#define SECT_L1 0 +#define SECT_L2 1 +#define SECT_L3 2 +#define SECT_STACK 3 + +// total number of section table entries in our PCB +#define N_SECTS 4 +// number of those that can be loaded from an ELF module +#define N_LOADABLE 3 + +/* +** The process control block +** +** Fields are ordered by size to avoid padding +** +** Currently, this is 72 bytes long. It could be reduced to 64 (2^6) +** bytes by making the last four fields uint16_t types; that would +** divide nicely into 1024 bytes, giving 16 PCBs per 1/4 page of memory. +*/ + +typedef struct pcb_s { + + // four-byte fields + // start with these four bytes, for easy access in assembly + context_t *context; // pointer to context save area on stack + + // VM information + pde_t *pdir; // page directory for this process + section_t sects[N_SECTS]; // per-section memory information + + // queue linkage + struct pcb_s *next; // next PCB in queue + + // process state information + struct pcb_s *parent; // pointer to PCB of our parent process + uint32_t wakeup; // wakeup time, for sleeping processes + int32_t exit_status; // termination status, for parent's use + + // these things may not need to be four bytes + uint_t pid; // PID of this process + enum state_e state; // process' current state + enum priority_e priority; // process priority level + uint_t ticks; // remaining ticks in this time slice + +} pcb_t; + +#define SZ_PCB sizeof(pcb_t) + +/* +** PCB queue structure (opaque to the rest of the kernel) +*/ +typedef struct pcb_queue_s *pcb_queue_t; + +/* +** Queue ordering methods +*/ +enum pcb_queue_order_e { + O_FIFO, O_PRIO, O_PID, O_WAKEUP + // sentinel + , N_ORDERINGS +}; +#define O_FIRST_STYLE O_FIFO +#define O_LAST_STYLE O_WAKEUP + +/* +** Globals +*/ + +// public-facing queue handles +extern pcb_queue_t pcb_freelist; +extern pcb_queue_t ready; +extern pcb_queue_t waiting; +extern pcb_queue_t sleeping; +extern pcb_queue_t zombie; +extern pcb_queue_t sioread; + +// pointer to the currently-running process +extern pcb_t *current; + +// the process table +extern pcb_t ptable[N_PROCS]; + +// next available PID +extern uint_t next_pid; + +// pointer to the PCB for the 'init' process +extern pcb_t *init_pcb; + +// table of state name strings +extern const char *state_str[N_STATES]; + +// table of priority name strings +extern const char *prio_str[N_PRIOS]; + +// table of queue ordering name strings +extern const char *ord_str[N_ORDERINGS]; + +/* +** Prototypes +*/ + +/** +** Name: pcb_init +** +** Initialization for the Process module. +*/ +void pcb_init( void ); + +/** +** Name: pcb_alloc +** +** Allocate a PCB from the list of free PCBs. +** +** @param pcb Pointer to a pcb_t * where the PCB pointer will be returned. +** +** @return status of the allocation attempt +*/ +int pcb_alloc( pcb_t **pcb ); + +/** +** Name: pcb_free +** +** Return a PCB to the list of free PCBs. +** +** @param pcb Pointer to the PCB to be deallocated. +*/ +void pcb_free( pcb_t *pcb ); + +/** +** Name: pcb_zombify +** +** Turn the indicated process into a Zombie. This function +** does most of the real work for exit() and kill() calls. +** Is also called from the scheduler and dispatcher. +** +** @param pcb Pointer to the newly-undead PCB +*/ +void pcb_zombify( register pcb_t *victim ); + +/** +** Name: pcb_cleanup +** +** Reclaim a process' data structures +** +** @param pcb The PCB to reclaim +*/ +void pcb_cleanup( pcb_t *pcb ); + +/** +** Name: pcb_find_pid +** +** Locate the PCB for the process with the specified PID +** +** @param pid The PID to be located +** +** @return Pointer to the PCB, or NULL +*/ +pcb_t *pcb_find_pid( uint_t pid ); + +/** +** Name: pcb_find_ppid +** +** Locate the PCB for the process with the specified parent +** +** @param pid The PID to be located +** +** @return Pointer to the PCB, or NULL +*/ +pcb_t *pcb_find_ppid( uint_t pid ); + +/** +** Name: pcb_queue_reset +** +** Initialize a PCB queue. +** +** @param queue[out] The queue to be initialized +** @param order[in] The desired ordering for the queue +** +** @return status of the init request +*/ +int pcb_queue_reset( pcb_queue_t queue, enum pcb_queue_order_e style ); + +/** +** Name: pcb_queue_empty +** +** Determine whether a queue is empty. Essentially just a wrapper +** for the PCB_QUEUE_EMPTY() macro, for use outside this module. +** +** @param[in] queue The queue to check +** +** @return true if the queue is empty, else false +*/ +bool_t pcb_queue_empty( pcb_queue_t queue ); + +/** +** Name: pcb_queue_length +** +** Return the count of elements in the specified queue. +** +** @param[in] queue The queue to check +** +** @return the count (0 if the queue is empty) +*/ +uint_t pcb_queue_length( const pcb_queue_t queue ); + +/** +** Name: pcb_queue_insert +** +** Inserts a PCB into the indicated queue. +** +** @param queue[in,out] The queue to be used +** @param pcb[in] The PCB to be inserted +** +** @return status of the insertion request +*/ +int pcb_queue_insert( pcb_queue_t queue, pcb_t *pcb ); + +/** +** Name: pcb_queue_peek +** +** Return the first PCB from the indicated queue, but don't +** remove it from the queue +** +** @param queue[in] The queue to be used +** +** @return the PCB pointer, or NULL if the queue is empty +*/ +pcb_t *pcb_queue_peek( const pcb_queue_t queue ); + +/** +** Name: pcb_queue_remove +** +** Remove the first PCB from the indicated queue. +** +** @param queue[in,out] The queue to be used +** @param pcb[out] Pointer to where the PCB pointer will be saved +** +** @return status of the removal request +*/ +int pcb_queue_remove( pcb_queue_t queue, pcb_t **pcb ); + +/** +** Name: pcb_queue_remove_this +** +** Remove the specified PCB from the indicated queue. +** +** @param queue[in,out] The queue to be used +** @param pcb[in] Pointer to the PCB to be removed +** +** @return status of the removal request +*/ +int pcb_queue_remove_this( pcb_queue_t queue, pcb_t *pcb ); + +/* +** Scheduler routines +*/ + +/** +** schedule(pcb) +** +** Schedule the supplied process +** +** @param pcb Pointer to the PCB of the process to be scheduled +*/ +void schedule( pcb_t *pcb ); + +/** +** dispatch() +** +** Select the next process to receive the CPU +*/ +void dispatch( void ); + +/* +** Debugging/tracing routines +*/ + +/** +** Name: ctx_dump +** +** Dumps the contents of this process context to the console +** +** @param msg[in] An optional message to print before the dump +** @param c[in] The context to dump out +*/ +void ctx_dump( const char *msg, register context_t *c ); + +/** +** Name: ctx_dump_all +** +** dump the process context for all active processes +** +** @param msg[in] Optional message to print +*/ +void ctx_dump_all( const char *msg ); + +/** +** Name: pcb_dump +** +** Dumps the contents of this PCB to the console +** +** @param msg[in] An optional message to print before the dump +** @param p[in] The PCB to dump +** @param all[in] Dump all the contents? +*/ +void pcb_dump( const char *msg, register pcb_t *p, bool_t all ); + +/** +** Name: pcb_queue_dump +** +** Dump the contents of the specified queue to the console +** +** @param msg[in] An optional message to print before the dump +** @param queue[in] The queue to dump +** @param contents[in] Also dump (some) contents? +*/ +void pcb_queue_dump( const char *msg, pcb_queue_t queue, bool_t contents ); + +/** +** Name: ptable_dump +** +** dump the contents of the "active processes" table +** +** @param msg[in] Optional message to print +** @param all[in] Dump all or only part of the relevant data +*/ +void ptable_dump( const char *msg, bool_t all ); + +/** +** Name: ptable_dump_counts +** +** Prints basic information about the process table (number of +** entries, number with each process state, etc.). +*/ +void ptable_dump_counts( void ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/sio.h b/include/sio.h new file mode 100644 index 0000000..dca80ed --- /dev/null +++ b/include/sio.h @@ -0,0 +1,168 @@ +/** +** @file sio.h +** +** @author Warren R. Carithers +** +** @brief SIO definitions +*/ + +#ifndef SIO_H_ +#define SIO_H_ + +// compatibility definitions +#include + +/* +** General (C and/or assembly) definitions +*/ + +// sio interrupt settings + +#define SIO_TX 0x01 +#define SIO_RX 0x02 +#define SIO_BOTH (SIO_TX | SIO_RX) + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +#include + +#include + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +// queue for read-blocked processes +extern QTYPE QNAME; + +/* +** PUBLIC FUNCTIONS +*/ + +/** +** sio_init() +** +** Initialize the UART chip. +*/ +void sio_init( void ); + +/** +** sio_enable() +** +** Enable SIO interrupts +** +** usage: uint8_t old = sio_enable( uint8_t which ) +** +** @param which Bit mask indicating which interrupt(s) to enable +** +** @return the prior IER setting +*/ +uint8_t sio_enable( uint8_t which ); + +/** +** sio_disable() +** +** Disable SIO interrupts +** +** usage: uint8_t old = sio_disable( uint8_t which ) +** +** @param which Bit mask indicating which interrupt(s) to disable +** +** @return the prior IER setting +*/ +uint8_t sio_disable( uint8_t which ); + +/** +** sio_inq_length() +** +** Get the input queue length +** +** usage: int num = sio_inq_length() +** +** @return the count of characters still in the input queue +*/ +int sio_inq_length( void ); + +/** +** sio_readc() +** +** Get the next input character +** +** usage: int ch = sio_readc() +** +** @return the next character, or -1 if no character is available +*/ +int sio_readc( void ); + +/** +** sio_read() +** +** Read the entire input buffer into a user buffer of a specified size +** +** usage: int num = sio_read( char *buffer, int length ) +** +** @param buf The destination buffer +** @param length Length of the buffer +** +** @return the number of bytes copied, or 0 if no characters were available +*/ +int sio_read( char *buffer, int length ); + +/** +** sio_writec( ch ) +** +** Write a character to the serial output +** +** usage: sio_writec( int ch ) +** +** @param ch Character to be written (in the low-order 8 bits) +*/ +void sio_writec( int ch ); + +/** +** sio_write( ch ) +** +** Write a buffer of characters to the serial output +** +** usage: int num = sio_write( const char *buffer, int length ) +** +** @param buffer Buffer containing characters to write +** @param length Number of characters to write +** +** @return the number of characters copied into the SIO output buffer +*/ +int sio_write( const char *buffer, int length ); + +/** +** sio_puts( buf ) +** +** Write a NUL-terminated buffer of characters to the serial output +** +** usage: n = sio_puts( const char *buffer ); +** +** @param buffer The buffer containing a NUL-terminated string +** +** @return the count of bytes transferred +*/ +int sio_puts( const char *buffer ); + +/** +** sio_dump( full ) +** +** Dump the contents of the SIO buffers to the console +** +** usage: sio_dump(true) or sio_dump(false) +** +** @param full Boolean indicating whether or not a "full" dump +** is being requested (which includes the contents +** of the queues) +*/ +void sio_dump( bool_t full ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/support.h b/include/support.h new file mode 100644 index 0000000..bdc5dc6 --- /dev/null +++ b/include/support.h @@ -0,0 +1,87 @@ +/** +** SCCS ID: @(#)support.h 2.3 1/22/25 +** +** @file support.h +** +** @author K. Reek +** @author Warren R. Carithers +** +** Declarations for functions provided in support.c, and +** some hardware characteristics needed in the initialization. +** +*/ + +#ifndef SUPPORT_H +#define SUPPORT_H + +/* +** Delay values +** +** Notes: The parameter to the delay() function is ambiguous; it +** purports to indicate a delay length, but that isn't really tied +** to any real-world time measurement. +** +** On the original systems we used (dual 500MHz Intel P3 CPUs), each +** "unit" was approximately one tenth of a second, so delay(10) would +** delay for about one second. +** +** On the current machines (Intel Core i5-7500), delay(100) is about +** 2.5 seconds, so each "unit" is roughly 0.025 seconds. +** +** Ultimately, just remember that THESE VALUES ARE APPROXIMATE AT BEST. +*/ +#define DELAY_1_SEC 40 +#define DELAY_1_25_SEC 50 +#define DELAY_2_SEC 80 +#define DELAY_2_5_SEC 100 +#define DELAY_3_SEC 120 +#define DELAY_5_SEC 200 +#define DELAY_7_SEC 280 +#define DELAY_10_SEC 400 + +#ifndef ASM_SRC +/** +** panic +** +** Called when we find an unrecoverable error, this routine disables +** interrupts, prints a description of the error and then goes into a +** hard loop to prevent any further processing. +** +** @param reason NUL-terminated message to be printed. +*/ +void panic( char *reason ); + +/** +** init_interrupts +** +** (Re)initilizes the interrupt system. This includes initializing the +** IDT and the PIC. It is up to the user to enable processor interrupts +** when they're ready. +*/ +void init_interrupts( void ); + +/* +** install_isr +** +** Installs a second-level handler for a specific interrupt. Returns the +** previously-installed handler for reinstallation (if desired). +** +** @param vector the interrupt vector number +** @param handler the second-stage ISR function to be called by the stub +** +** @return a pointer to the previously-registered ISR +*/ +void (*install_isr( int vector, + void ( *handler )(int,int) ) )( int, int ); + +/* +** Name: delay +** +** See the comment above about the relative accuracy of the 'length' +** parameter. +*/ +void delay( int length ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/syscalls.h b/include/syscalls.h new file mode 100644 index 0000000..e66f6c0 --- /dev/null +++ b/include/syscalls.h @@ -0,0 +1,80 @@ +/** +** @file syscalls.h +** +** @author CSCI-452 class of 20245 +** +** @brief System call declarations +*/ + +#ifndef SYSCALLS_H_ +#define SYSCALLS_H_ + +#include + +/* +** General (C and/or assembly) definitions +*/ + +/* +** system call codes +** +** these are used in the user-level C library stub functions, +** and are defined here as CPP macros instead of as an enum +** so that they can be used from assembly +*/ + +#define SYS_exit 0 +#define SYS_waitpid 1 +#define SYS_fork 2 +#define SYS_exec 3 +#define SYS_read 4 +#define SYS_write 5 +#define SYS_getpid 6 +#define SYS_getppid 7 +#define SYS_gettime 8 +#define SYS_getprio 9 +#define SYS_setprio 10 +#define SYS_kill 11 +#define SYS_sleep 12 + +// UPDATE THIS DEFINITION IF MORE SYSCALLS ARE ADDED! +#define N_SYSCALLS 13 + +// dummy system call code for testing our ISR +#define SYS_bogus 0xbad + +// interrupt vector entry for system calls +#define VEC_SYSCALL 0x80 + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Types +*/ + +/* +** Globals +*/ + +/* +** Prototypes +*/ + +#ifdef KERNEL_SRC + +/** +** Name: sys_init +** +** Syscall module initialization routine +*/ +void sys_init( void ); + +#endif /* KERNEL_SRC */ + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/types.h b/include/types.h new file mode 100644 index 0000000..2f934f1 --- /dev/null +++ b/include/types.h @@ -0,0 +1,58 @@ +/** +** @file types.h +** +** @author Warren R. Carithers +** +** @brief Common type declarations. +** +** This header file contains type declarations used throughout +** the kernel and user code. +*/ + +#ifndef TYPES_H_ +#define TYPES_H_ + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +** +** Anything that should not be visible to something other than +** the C compiler should be put here. +*/ + +/* +** Types +*/ + +// standard integer sized types +typedef char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; + +// other integer types +typedef unsigned char uchar_t; +typedef unsigned int uint_t; +typedef unsigned long int ulong_t; + +// Boolean values +typedef uint8_t bool_t; + +#define true 1 +#define false 0 + +#ifdef KERNEL_SRC +// we define these here instead of in vm.h in order to get around a +// nasty chick/egg dependency between procs.h and vm.h +typedef uint32_t pde_t; // page directory entry +typedef uint32_t pte_t; // page table entry +#endif /* KERNEL_SRC */ + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/udefs.h b/include/udefs.h new file mode 100644 index 0000000..50b6952 --- /dev/null +++ b/include/udefs.h @@ -0,0 +1,113 @@ +/** +** @file udefs.h +** +** @author CSCI-452 class of 20245 +** +** @brief "Userland" configuration information +*/ + +#ifndef UDEFS_H_ +#define UDEFS_H_ + +#include + +/* +** General (C and/or assembly) definitions +** +** This section of the header file contains definitions that can be +** used in either C or assembly-language source code. +*/ + +// delay loop counts + +#define DELAY_LONG 100000000 +#define DELAY_MED 4500000 +#define DELAY_SHORT 2500000 + +#define DELAY_STD DELAY_SHORT + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +// convenience macros + +// a delay loop - kind of ugly, but it works + +#define DELAY(n) do { \ + for(int _dlc = 0; _dlc < (DELAY_##n); ++_dlc) continue; \ + } while(0) + +/* +** We need the list of program IDs so that we can request +** their execution +*/ + +#include + +/* +** All user main() functions have the following prototype: +** +** int name( int argc, char *argv[] ); +** +** To simplify declaring them, we define a macro that expands into +** that header. This can be used both in the implementation (followed +** by the function body) and in places where we just need the prototype +** (following it with a semicolon). +*/ + +#define USERMAIN(f) int f( int argc, char *argv[] ) + +/* +** User process controls. +** +** To enable a specific test, define the symbol SPAWN_name here, and +** guard the places in other code that use or refer to that test. For +** example, test 'A' is enabled by definining SPAWN_A here, and all +** places that refer to test 'A' are guarded with: +** +** #ifdef SPAWN_A +** ... conditionally-compiled code +** #endif +** +** Generally, most of these will exit with a status of 0. If a process +** returns from its main function when it shouldn't (e.g., if it had +** called exit() but continued to run), it will usually return a status +** of ?. +*/ + +/* +** The standard set of test programs, start by the shell (which is started +** automatically from the initial user process) +** +** There is no user 'O' program, and programs 'W' through 'Z' are spawned +** from other processes and are never spawned directly. +*/ + +#define SPAWN_A +#define SPAWN_B +#define SPAWN_C +#define SPAWN_D +#define SPAWN_E +#define SPAWN_F +#define SPAWN_G +#define SPAWN_H +#define SPAWN_I +#define SPAWN_J +#define SPAWN_K +#define SPAWN_L +#define SPAWN_M +#define SPAWN_N +#define SPAWN_P +#define SPAWN_Q +#define SPAWN_R +#define SPAWN_S +#define SPAWN_T +#define SPAWN_U +#define SPAWN_V + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/ulib.h b/include/ulib.h new file mode 100644 index 0000000..d254d6a --- /dev/null +++ b/include/ulib.h @@ -0,0 +1,315 @@ +/** +** @file ulib.h +** +** @author CSCI-452 class of 20245 +** +** @brief Declarations for user-level library functions +** +** This module implements a simple collection of support functions +** similar to the standard C library. +*/ + +#ifndef ULIB_H_ +#define ULIB_H_ + +#include + +/* +** General (C and/or assembly) definitions +*/ + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Types +*/ + +/* +** Globals +*/ + +/* +** Prototypes +*/ + +/* +************************************************* +** SYSTEM CALLS ********************************* +************************************************* +*/ + +/** +** exit - terminate the calling process +** +** usage: exit(status); +** +** @param status Termination status of this process +** +** Does not return. +*/ +void exit( int32_t status ); + +/** +** waitpid - wait for a child process to terminate +** +** usage: pid = waitpid(pid,&status); +** +** @param pid PID of the desired child, or 0 for any child +** @param status Pointer to int32_t into which the child's status is placed, +** or NULL +** +** @return The PID of the terminated child, or an error code +** +** If there are no children in the system, returns an error code (*status +** is unchanged). +** +** If there are one or more children in the system and at least one has +** terminated but hasn't yet been cleaned up, cleans up that process and +** returns its information; otherwise, blocks until a child terminates. +*/ +int waitpid( uint_t pid, int32_t *status ); + +/** +** fork - create a duplicate of the calling process +** +** usage: pid = fork(); +** +** @return parent - the pid of the new child, or an error code +** child - 0 +*/ +int fork( void ); + +/** +** exec - replace the memory image of the calling process +** +** usage: exec( what, args ) +** +** @param what program table index of the program to exec +** @param args the command-line argument vector +** +** Does not return if it succeeds; if it returns, something has +** gone wrong. +*/ +void exec( uint_t what, char **args ); + +/** +** read - read into a buffer from a stream +** +** usage: n = read(channel,buf,length) +** +** @param chan I/O stream to read from +** @param buf Buffer to read into +** @param length Maximum capacity of the buffer +** +** @return The count of bytes transferred, or an error code +*/ +int read( uint_t chan, void *buffer, uint_t length ); + +/** +** write - write from a buffer to a stream +** +** usage: n = write(channel,buf,length) +** +** @param chan I/O stream to write to +** @param buf Buffer to write from +** @param length Maximum capacity of the buffer +** +** @return The count of bytes transferred, or an error code +*/ +int write( uint_t chan, const void *buffer, uint_t length ); + +/** +** getpid - get the PID of the calling process +** +** usage: pid = getpid() +** +** @return the PID of this process +*/ +uint_t getpid( void ); + +/** +** getppid - get the PID of the calling process' parent +** +** usage: pid = getppid() +** +** @return the PID of this process' parent +*/ +uint_t getppid( void ); + +/** +** gettime - get the current system time +** +** usage: pid = gettime() +** +** @return the system time +*/ +uint32_t gettime( void ); + +/** +** getprio - get the scheduling priority of the calling process +** +** usage: prio = getprio() +** +** @return the process' priority +*/ +int getprio( void ); + +/** +** setprio - set the scheduling priority of the calling process +** +** usage: oldprio = setprio(newprio) +** +** @param new the desired new priority +** +** @return the old priority value +*/ +int setprio( int new ); + +/** +** kill - terminate a process with extreme prejudice +** +** usage: n = kill( pid ) +** +** @param pid the intended victim +** +** @return 0 on success, else an error code +*/ +int32_t kill( uint_t pid ); + +/** +** sleep - put the current process to sleep for some length of time +** +** usage: sleep(n); +** +** @param ms Desired sleep time (in ms), or 0 to yield the CPU +** +** @return the time the process spent sleeping (in ms) +*/ +int sleep( uint32_t ms ); + +/** +** bogus - a nonexistent system call, to test our syscall ISR +** +** usage: bogus() +** +** Does not return. +*/ +void bogus( void ); + +/* +************************************************* +** CONVENIENT "SHORTHAND" VERSIONS OF SYSCALLS ** +************************************************* +** +** These are library functions that perform specific common +** variants of system calls. This helps reduce the total number +** of system calls, keeping our baseline OS as lean and mean +** as we can make it. :-) +*/ + +/** +** wait - wait for any child to exit +** +** usage: pid = wait(&status) +** +** Calls waitpid(0,status) +** +** @param status Pointer to int32_t into which the child's status is placed, +** or NULL +** +** @return The PID of the terminated child, or an error code +*/ +int wait( int32_t *status ); + +/** +** spawn - create a new process running a different program +** +** usage: n = spawn(what,args) +** +** Creates a new process and then execs 'what' +** +** @param what Program table index of the program to spawn +** @param args The command-line argument vector for the process +** +** @return The PID of the child, or an error code +*/ +int spawn( uint_t what, char **args ); + +/** +** cwritech(ch) - write a single character to the console +** +** @param ch The character to write +** +** @return The return value from calling write() +*/ +int cwritech( char ch ); + +/** +** cwrites(str) - write a NUL-terminated string to the console +** +** @param str The string to write +** +*/ +int cwrites( const char *str ); + +/** +** cwrite(buf,leng) - write a sized buffer to the console +** +** @param buf The buffer to write +** @param leng The number of bytes to write +** +** @return The return value from calling write() +*/ +int cwrite( const char *buf, uint32_t leng ); + +/** +** swritech(ch) - write a single character to the SIO +** +** @param ch The character to write +** +** @return The return value from calling write() +*/ +int swritech( char ch ); + +/** +** swrites(str) - write a NUL-terminated string to the SIO +** +** @param str The string to write +** +** @return The return value from calling write() +*/ +int swrites( const char *str ); + +/** +** swrite(buf,leng) - write a sized buffer to the SIO +** +** @param buf The buffer to write +** @param leng The number of bytes to write +** +** @return The return value from calling write() +*/ +int swrite( const char *buf, uint32_t leng ); + +/* +************************************************* +** MISCELLANEOUS USEFUL SUPPORT FUNCTIONS ******* +************************************************* +*/ + +/** +** fake_exit() +** +** dummy "startup" function +** +** calls exit(%eax) - serves as the "return to" code for +** main() functions, in case they don't call exit() themselves +*/ +void fake_exit( void ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/user.h b/include/user.h new file mode 100644 index 0000000..4d9402f --- /dev/null +++ b/include/user.h @@ -0,0 +1,138 @@ +/** +** @file user.h +** +** @author CSCI-452 class of 20245 +** +** @brief Declarations of user-level code management routines +*/ + +#ifndef USER_H_ +#define USER_H_ + +#include + +#include +#include + +// default value for EFLAGS in new processes +#define DEFAULT_EFLAGS (EFL_MB1 | EFL_IF) + +/* +** General (C and/or assembly) definitions +*/ + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Types +*/ + +/* +** Blob file organization +** +** The file begins with a four-byte magic number and a four-byte integer +** indicating the number of ELF files contained in the blob. This is +** followed by an array of 32-byte file table entries, and then the contents +** of the ELF files in the order they appear in the program file table. +** +** Bytes Contents +** ----- ---------------------------- +** 0 - 3 File magic number ("BLB\0") +** 4 - 7 Number of ELF files in blob ("n") +** 8 - n*32+8 Program file table +** n*32+9 - ? ELF file contents +** +** Each program file table entry contains the following information: +** +** name File name (up to 19 characters long) +** offset Byte offset to the ELF header for this file +** size Size of this ELF file, in bytes +** flags Flags related to this file +*/ + +// user program blob header +typedef struct header_s { + char magic[4]; + uint32_t num; +} header_t; + +// length of the file name field +#define NAMELEN 20 + +// program descriptor +typedef struct prog_s { + char name[NAMELEN]; // truncated name (15 chars) + uint32_t offset; // offset from the beginning of the blob + uint32_t size; // size of this ELF module + uint32_t flags; // miscellaneous flags +} prog_t; + +/* +** Globals +*/ + +/* +** Prototypes +*/ + +/** +** Name: user_init +** +** Initializes the user support module. +*/ +void user_init( void ); + +/** +** Name: user_locate +** +** Locates a user program in the user code archive. +** +** @param what The ID of the user program to find +** +** @return pointer to the program table entry in the code archive, or NULL +*/ +prog_t *user_locate( uint_t what ); + +/** +** Name: user_duplicate +** +** Duplicates the memory setup for an existing process. +** +** @param new The PCB for the new copy of the program +** @param old The PCB for the existing the program +** +** @return the status of the duplicate attempt +*/ +int user_duplicate( pcb_t *new, pcb_t *old ); + +/** +** Name: user_load +** +** Loads a user program from the user code archive into memory. +** Allocates all needed frames and sets up the VM tables. +** +** @param prog A pointer to the program table entry to be loaded +** @param pcb The PCB for the program being loaded +** @param args The argument vector for the program +** +** @return the status of the load attempt +*/ +int user_load( prog_t *prog, pcb_t *pcb, const char **args ); + +/** +** Name: user_cleanup +** +** "Unloads" a user program. Deallocates all memory frames and +** cleans up the VM structures. +** +** @param pcb The PCB of the program to be cleaned up +*/ +void user_cleanup( pcb_t *pcb ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/userids.h b/include/userids.h new file mode 100644 index 0000000..284f3ee --- /dev/null +++ b/include/userids.h @@ -0,0 +1,33 @@ +/** +** @file userids.h +** +** @author Warren R. Carithers +** +** @brief IDs for user-level programs +** +** NOTE: this file is automatically generated when the user.img file +** is created. Do not edit this manually! +*/ + +#ifndef USERIDS_H_ +#define USERIDS_H_ + +#ifndef ASM_SRC +/* +** These IDs are used to identify the various user programs. +** Each call to exec() will provide one of these as the first +** argument. +** +** This list should be updated if/when the collection of +** user processes changes. +*/ +enum users_e { + Init, Idle, Shell, ProgABC, ProgDE, ProgFG, ProgH, ProgI, + ProgJ, ProgKL, ProgMN, ProgP, ProgQ, ProgR, ProgS, ProgTUV, + ProgW, ProgX, ProgY, ProgZ + // sentinel + , N_USERS +}; +#endif /* !ASM_SRC */ + +#endif diff --git a/include/vm.h b/include/vm.h new file mode 100644 index 0000000..d557d5e --- /dev/null +++ b/include/vm.h @@ -0,0 +1,433 @@ +/** +** @file vm.h +** +** @author CSCI-452 class of 20245 +** +** @brief Virtual memory-related declarations. +*/ + +#ifndef VM_H_ +#define VM_H_ + +#include +#include + +#include + +/* +** VM layout of the system +** +** User processes use the first 4MB of the 32-bit address space; see the +** next comment for details. +** +** Kernel virtual addresses are in the "higher half" range, beginning +** at 0x80000000. We define our mapping such that virtual address +** 0x8nnnnnnn maps to physical address 0x0nnnnnnn, so converting between +** the two is trivial. +*/ + +/* +** VM layout of process' address space +** +** Processes are limited to the first 4MB of the 32-bit address space: +** +** Address Range Contents +** ======================= ================================ +** 0x00000000 - 0x00000fff page 0 is inaccessible +** 0x00001000 - 0x000..fff text occupies pages 1 - N +** 0x000..000 - 0x000..fff data occupies pages N+1 - N+d +** 0x000..000 - 0x000..fff bss occupies pages N+d+1 - N+d+b +** 0x000..000 - 0x003fdfff unusable +** 0x003fe000 - 0x003fffff stack occupies last two pages +** +** This gives us the following page table structure: +** +** Page directory: +** Entries Contents +** ======== ============================== +** 0 point to PMT for address space +** 1 - 1023 invalid +** +** Page map table: +** Entries Contents +** ======== ============================== +** 0 invalid +** 1 - N text frames +** N+1 - N+d data frames +** N+d+1 - N+d+b bss frames +** N+d+b+1 - 1021 invalid +** 1022 - 1023 stack frames +*/ + +/* +** General (C and/or assembly) definitions +*/ + +// user virtual addresses +#define USER_TEXT 0x00001000 +#define USER_STACK 0x003fe000 +#define USER_STK_END 0x00400000 + +// how to find the addresses of the stack pages in the VM hierarchy +// user address space is the first 4MB of virtual memory +#define USER_PDE 0 +// the stack occupies the last two pages of the address space +#define USER_STK_PTE1 1022 +#define USER_STK_PTE2 1023 + +// some important memory addresses +#define KERN_BASE 0x80000000 // start of "kernel" memory +#define EXT_BASE 0x00100000 // start of "extended" memory (1MB) +#define DEV_BASE 0xfe000000 // "device" memory +#define PHYS_TOP 0x7fffffff // last usable physical address + +// where the kernel actually lives +#define KERN_PLINK 0x00010000 +#define KERN_VLINK (KERN_BASE + KERN_PLINK) + +// physical/virtual converters +#ifndef ASM_SRC +// uses casting +#define V2P(a) (((uint_t)(a)) - KERN_BASE) +#define P2V(a) ((void *)(((uint_t)(a)) + KERN_BASE)) +#else +// doesn't use casting +#define V2P(a) ((a) - KERN_BASE) +#define P2V(a) ((a) + KERN_BASE) +#endif /* !ASM_SRC */ + +// number of entries in a page directory or page table +#define N_PDE 1024 +#define N_PTE 1024 + +// index field shift counts and masks +#define PDIX_SHIFT 22 +#define PTIX_SHIFT 12 +#define PIX2I_MASK 0x3ff + +#ifndef ASM_SRC +// 4KB frame numbers are 20 bits wide +#define FRAME_4K_SHIFT 12 +#define F2I_4K_MASK 0x000fffff +#define TO_4KFRAME(n) (((n)&F2I_4K_MASK) << FRAME_4K_SHIFT) +#define GET_4KFRAME(n) (((n) >> FRAME_4K_SHIFT)&F2I_4K_MASK) + +// 4MB frame numbers are 10 bits wide +#define FRAME_4M_SHIFT 22 +#define F2I_4M_MASK 0x000003ff +#define TO_4MFRAME(n) (((n)&F2I_4M_MASK) << FRAME_4M_SHIFT) +#define GET_4MFRAME(n) (((n) >> FRAME_4M_SHIFT)&F2I_4M_MASK) + +// extract the PMT address or frame address from a table entry +#define FRAME_MASK MOD4K_MASK +#define PERM_MASK MOD4K_BITS +#define PDE_ADDR(p) (((uint32_t)(p))&FRAME_MASK) +#define PTE_ADDR(p) (((uint32_t)(p))&FRAME_MASK) +#define PERMS(p) (((uint32_t)(p))&PERM_MASK) + +// extract the table indices from a 32-bit address +#define PDIX(v) ((((uint32_t)(v)) >> PDIX_SHIFT) & PIX2I_MASK) +#define PTIX(v) ((((uint32_t)(v)) >> PTIX_SHIFT) & PIX2I_MASK) + +// page-size address rounding macros +#define SZ_PG_M1 MOD4K_BITS +#define SZ_PG_MASK MOD4K_MASK +#define PGUP(a) (((a)+SZ_PG_M1) & SZ_PG_MASK) +#define PGDOWN(a) ((a) & SZ_PG_MASK) + +// page directory entry fields +#define PDE_P 0x00000001 +#define PDE_RW 0x00000002 +#define PDE_US 0x00000004 +#define PDE_PWT 0x00000008 +#define PDE_PCD 0x00000010 +#define PDE_A 0x00000020 +#define PDE_AVL1 0x00000040 +#define PDE_PS 0x00000080 +#define PDE_AVL2 0x00000f00 +#define PDE_BA 0xfffff000 + +// page table entry fields +#define PTE_P 0x00000001 +#define PTE_RW 0x00000002 +#define PTE_US 0x00000004 +#define PTE_PWT 0x00000008 +#define PTE_PCD 0x00000010 +#define PTE_A 0x00000020 +#define PTE_D 0x00000040 +#define PTE_PAT 0x00000080 +#define PTE_G 0x00000100 +#define PTE_AVL2 0x00000e00 +#define PTE_FA 0xfffff000 + +#define PG_CODE (PTE_USER | PTE_PRESENT) +#define PG_DATA (PTE_USER | PTE_RW | PTE_PRESENT) + +// error code bit assignments for page faults +#define PFLT_P 0x00000001 +#define PFLT_W 0x00000002 +#define PFLT_US 0x00000004 +#define PFLT_RSVD 0x00000008 +#define PFLT_ID 0x00000010 +#define PFLT_PK 0x00000020 +#define PFLT_SS 0x00000040 +#define PFLT_HLAT 0x00000080 +#define PFLT_SGX 0x00008000 +#define PFLT_UNUSED 0xffff7f00 + +// create a pde/pte from an integer frame number and permission bits +#define MKPDE(f,p) ((pde_t)( TO_FRAME((f)) | (p) )) +#define MKPTE(f,p) ((pte_t)( TO_FRAME((f)) | (p) )) + +// is a PDE/PTE present? +// (P bit is in the same place in both) +#define IS_PRESENT(entry) (((entry) & PDE_P) != 0 ) + +// is a PDE a 4MB page entry? +#define IS_LARGE(pde) (((pde) & PDE_PS) != 0 ) +#endif /* !ASM_SRC */ + +#ifndef ASM_SRC + +/* +** Start of C-only definitions +*/ + +/* +** Types +*/ + +// page directory entries + +// as a 32-bit word, in types.h +// typedef uint32_t pde_t; + +// PDE for 4KB pages +typedef struct pdek_s { + uint_t p :1; // present + uint_t rw :1; // writable + uint_t us :1; // user/supervisor + uint_t pwt :1; // cache write-through + uint_t pcd :1; // cache disable + uint_t a :1; // accessed + uint_t avl1 :1; // ignored (available) + uint_t ps :1; // page size (must be 0) + uint_t avl2 :4; // ignored (available) + uint_t fa :20; // frame address +} pdek_f_t; + +// PDE for 4MB pages +typedef struct pdem_s { + uint_t p :1; // present + uint_t rw :1; // writable + uint_t us :1; // user/supervisor + uint_t pwt :1; // cache write-through + uint_t pcd :1; // cache disable + uint_t a :1; // accessed + uint_t d :1; // dirty + uint_t ps :1; // page size (must be 1) + uint_t g :1; // global + uint_t avl :3; // ignored (available) + uint_t fa :20; // frame address +} pdem_f_t; + +// page table entries + +// as a 32-bit word, in types.h +// typedef uint32_t pte_t; + +// broken out into fields +typedef struct pte_s { + uint_t p :1; // present + uint_t rw :1; // writable + uint_t us :1; // user/supervisor + uint_t pwt :1; // cache write-through + uint_t pcd :1; // cache disable + uint_t a :1; // accessed + uint_t d :1; // dirty + uint_t pat :1; // page attribute table in use + uint_t g :1; // global + uint_t avl :3; // ignored (available) + uint_t fa :20; // frame address +} ptef_t; + +// page fault error code bits +// comment: meaning when 1 / meaning when 0 +struct pfec_s { + uint_t p :1; // page-level protection violation / !present + uint_t w :1; // write / read + uint_t us :1; // user-mode access / supervisor-mode access + uint_t rsvd :1; // reserved bit violation / not + uint_t id :1; // instruction fetch / data fetch + uint_t pk :1; // protection-key violation / !pk + uint_t ss :1; // shadow stack access / !ss + uint_t hlat :1; // HLAT paging / ordinary paging or access rights + uint_t xtr1 :7; // unused + uint_t sgz :1; // SGX-specific access control violation / !SGX + uint_t xtr2 :16; // more unused +}; + +typedef union pfec_u { + uint32_t u; + struct pfec_s s; +} pfec_t; + +// Mapping descriptor for VA::PA mappings +typedef struct mapping_t { + uint32_t va_start; // starting virtual address for this range + uint32_t pa_start; // first physical address in the range + uint32_t pa_end; // last physical address in the range + uint32_t perm; // access control +} mapping_t; + +/* +** Globals +*/ + +// created page directory for the kernel +extern pde_t *kpdir; + +/* +** Prototypes +*/ + +/** +** Name: vm_init +** +** Initialize the VM module +** +** Note: should not be called until after the memory free list has +** been set up. +*/ +void vm_init( void ); + +/** +** Name: vm_pagedup +** +** Duplicate a page of memory +** +** @param old Pointer to the first byte of a page +** +** @return a pointer to the new, duplicate page, or NULL +*/ +void *vm_pagedup( void *old ); + +/** +** Name: vm_ptdup +** +** Duplicate a page directory entry +** +** @param dst Pointer to where the duplicate should go +** @param curr Pointer to the entry to be duplicated +** +** @return true on success, else false +*/ +bool_t vm_ptdup( pde_t *dst, pde_t *curr ); + +/** +** Name: vm_getpte +** +** Return the address of the PTE corresponding to the virtual address +** 'va' within the address space controlled by 'pgdir'. If there is no +** page table for that VA and 'alloc' is true, create the necessary +** page table entries. +** +** @param pdir Pointer to the page directory to be searched +** @param va The virtual address we're looking for +** @param alloc Should we allocate a page table if there isn't one? +** +** @return A pointer to the page table entry for this VA, or NULL +*/ +pte_t *vm_getpte( pde_t *pdir, const void *va, bool_t alloc ); + +/** +** Name: vm_mkkvm +** +** Create the kernel's page table hierarchy +*/ +pde_t *vm_mkkvm( void ); + +/** +** Name: vm_mkuvm +** +** Create the page table hierarchy for a user process +*/ +pde_t *vm_mkuvm( void ); + +/** +** Name: vm_set_kvm +** +** Switch the page table register to the kernel's page directory +*/ +void vm_set_kvm( void ); + +/** +** Name: vm_set_uvm +** +** Switch the page table register to the page directory for a user process. +** +** @param p The PCB of the user process +*/ +void vm_set_uvm( pcb_t *p ); + +/** +** Name: vm_add +** +** Add pages to the page hierarchy for a process, copying data into +** them if necessary. +** +** @param pdir Pointer to the page directory to modify +** @param wr "Writable" flag for the PTE +** @param sys "System" flag for the PTE +** @param va Starting VA of the range +** @param size Amount of physical memory to allocate +** @param data Pointer to data to copy, or NULL +** @param bytes Number of bytes to copy +** +** @return status of the allocation attempt +*/ +int vm_add( pde_t *pdir, bool_t wr, bool_t sys, + void *va, uint32_t size, char *data, uint32_t bytes ); + +/** +** Name: vm_free +** +** Deallocate a page table hierarchy and all physical memory frames +** in the user portion. +** +** @param pdir Pointer to the page directory +*/ +void vm_free( pde_t *pdir ); + +/* +** Name: vm_map +** +** Create PTEs for virtual addresses starting at 'va' that refer to +** physical addresses in the range [pa, pa+size-1]. We aren't guaranteed +** that va is page-aligned. +** +** @param pdir Page directory for this address space +** @param va The starting virtual address +** @param size Length of the range to be mapped +** @param pa The starting physical address +** @param perm Permission bits for the PTEs +*/ +int vm_map( pde_t *pdir, void *va, uint_t size, uint_t pa, int perm ); + +/** +** Name: vm_uvmdup +** +** Create a duplicate of the user portio of an existing page table +** hierarchy. We assume that the "new" page directory exists and +** the system portions of it should not be touched. +** +** @param old Existing page directory +** @param new New page directory +** +** @return status of the duplication attempt +*/ +int vm_uvmdup( pde_t *old, pde_t *new ); + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/vmtables.h b/include/vmtables.h new file mode 100644 index 0000000..17f6e0a --- /dev/null +++ b/include/vmtables.h @@ -0,0 +1,43 @@ +/** +** @file vmtables.h +** +** @author CSCI-452 class of 20245 +** +** @brief Predefined VM tables +*/ + +#ifndef VMTABLES_H_ +#define VMTABLES_H_ + +#include +#include +#include + +#ifndef ASM_SRC + +/* +** Initial page directory, for when the kernel is starting up +** +** we use large (4MB) pages here to allow us to use a one-level +** paging hierarchy; the kernel will create a new page table +** hierarchy once memory is initialized +*/ +extern pde_t firstpdir[]; + +/* +** "Identity" page map table. +** +** This just maps the first 4MB of physical memory. It is initialized +** in vm_init(). +*/ +extern pte_t id_map[]; + +/* +** Kernel address mappings, present in every page table +*/ +extern mapping_t kmap[]; +extern const uint32_t n_kmap; + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/x86/arch.h b/include/x86/arch.h new file mode 100644 index 0000000..113c76b --- /dev/null +++ b/include/x86/arch.h @@ -0,0 +1,303 @@ +/* +** @file arch.h +** +** @author Warren R. Carithers +** @author K. Reek +** +** Definitions of constants and macros for use +** with the x86 architecture and registers. +** +*/ + +#ifndef X86ARCH_H_ +#define X86ARCH_H_ + +/* +** Video stuff +*/ +#define VID_BASE_ADDR 0xB8000 + +/* +** Memory management +*/ +#define SEG_PRESENT 0x80 +#define SEG_PL_0 0x00 +#define SEG_PL_1 0x20 +#define SEG_PL_2 0x40 +#define SEG_PL_3 0x50 +#define SEG_SYSTEM 0x00 +#define SEG_NON_SYSTEM 0x10 +#define SEG_32BIT 0x04 +#define DESC_IGATE 0x06 + +/* +** Exceptions +*/ +#define N_EXCEPTIONS 256 + +/* +** Bit definitions in registers +** +** See IA-32 Intel Architecture SW Dev. Manual, Volume 3: System +** Programming Guide, page 2-8. +*/ + +/* +** EFLAGS +*/ +#define EFL_RSVD 0xffc00000 /* reserved */ +#define EFL_MB0 0x00008020 /* must be zero */ +#define EFL_MB1 0x00000002 /* must be 1 */ + +#define EFL_ID 0x00200000 +#define EFL_VIP 0x00100000 +#define EFL_VIF 0x00080000 +#define EFL_AC 0x00040000 +#define EFL_VM 0x00020000 +#define EFL_RF 0x00010000 +#define EFL_NT 0x00004000 +#define EFL_IOPL 0x00003000 +#define EFL_OF 0x00000800 +#define EFL_DF 0x00000400 +#define EFL_IF 0x00000200 +#define EFL_TF 0x00000100 +#define EFL_SF 0x00000080 +#define EFL_ZF 0x00000040 +#define EFL_AF 0x00000010 +#define EFL_PF 0x00000004 +#define EFL_CF 0x00000001 + +/* +** CR0, CR1, CR2, CR3, CR4 +** +** IA-32 V3, page 2-12. +*/ +#define CR0_RSVD 0x1ffaffc0 +#define CR0_PG 0x80000000 +#define CR0_CD 0x40000000 +#define CR0_NW 0x20000000 +#define CR0_AM 0x00040000 +#define CR0_WP 0x00010000 +#define CR0_NE 0x00000020 +#define CR0_ET 0x00000010 +#define CR0_TS 0x00000008 +#define CR0_EM 0x00000004 +#define CR0_MP 0x00000002 +#define CR0_PE 0x00000001 + +#define CR1_RSVD 0xffffffff + +#define CR2_RSVD 0x00000000 +#define CR2_PF_LIN_ADDR 0xffffffff + +#define CR3_RSVD 0x00000fe7 +#define CR3_PD_BASE 0xfffff000 +#define CR3_PCD 0x00000010 +#define CR3_PWT 0x00000008 + +#define CR4_RSVD 0xfd001000 +#define CR4_UINT 0x02000000 +#define CR4_PKS 0x01000000 +#define CR4_CET 0x00800000 +#define CR4_PKE 0x00400000 +#define CR4_SMAP 0x00200000 +#define CR4_SMEP 0x00100000 +#define CR4_KL 0x00080000 +#define CR4_OSXS 0x00040000 +#define CR4_PCID 0x00020000 +#define CR4_FSGS 0x00010000 +#define CR4_SMXE 0x00004000 +#define CR4_VMXE 0x00002000 +#define CR4_LA57 0x00001000 +#define CR4_UMIP 0x00000800 +#define CR4_OSXMMEXCPT 0x00000400 +#define CR4_OSFXSR 0x00000200 +#define CR4_PCE 0x00000100 +#define CR4_PGE 0x00000080 +#define CR4_MCE 0x00000040 +#define CR4_PAE 0x00000020 +#define CR4_PSE 0x00000010 +#define CR4_DE 0x00000008 +#define CR4_TSD 0x00000004 +#define CR4_PVI 0x00000002 +#define CR4_VME 0x00000001 + +/* +** PMode segment selector field masks +** +** IA-32 V3, page 3-8. +*/ +#define SEG_SEL_IX_MASK 0xfff8 +#define SEG_SEL_TI_MASK 0x0004 +#define SEG_SEL_RPL_MASK 0x0003 + +/* +** Segment descriptor bytes +** +** IA-32 V3, page 3-10. +** +** Bytes: +** 0, 1: segment limit 15:0 +** 2, 3: base address 15:0 +** 4: base address 23:16 +** 7: base address 31:24 +*/ + +/* +** Byte 5: access control bits +** 7: present +** 6-5: DPL +** 4: system/user +** 3-0: type +*/ +#define SEG_ACCESS_P_MASK 0x80 +# define SEG_PRESENT 0x80 +# define SEG_NOT_PRESENT 0x00 + +#define SEG_ACCESS_DPL_MASK 0x60 +# define SEG_DPL_0 0x00 +# define SEG_DPL_1 0x20 +# define SEG_DPL_2 0x40 +# define SEG_DPL_3 0x60 + +#define SEG_ACCESS_S_MASK 0x10 +# define SEG_SYSTEM 0x00 +# define SEG_NON_SYSTEM 0x10 + +#define SEG_TYPE_MASK 0x0f +# define SEG_DATA_A_BIT 0x1 +# define SEG_DATA_W_BIT 0x2 +# define SEG_DATA_E_BIT 0x4 +# define SEG_CODE_A_BIT 0x1 +# define SEG_CODE_R_BIT 0x2 +# define SEG_CODE_C_BIT 0x4 +# define SEG_DATA_RO 0x0 +# define SEG_DATA_ROA 0x1 +# define SEG_DATA_RW 0x2 +# define SEG_DATA_RWA 0x3 +# define SEG_DATA_RO_XD 0x4 +# define SEG_DATA_RO_XDA 0x5 +# define SEG_DATA_RW_XW 0x6 +# define SEG_DATA_RW_XWA 0x7 +# define SEG_CODE_XO 0x8 +# define SEG_CODE_XOA 0x9 +# define SEG_CODE_XR 0xa +# define SEG_CODE_XRA 0xb +# define SEG_CODE_XO_C 0xc +# define SEG_CODE_XO_CA 0xd +# define SEG_CODE_XR_C 0xe +# define SEG_CODE_XR_CA 0xf + +/* +** Byte 6: sizes +** 7: granularity +** 6: d/b +** 5: long mode +** 4: available! +** 3-0: upper 4 bits of limit +** 7: base address 31:24 +*/ +#define SEG_SIZE_G_MASK 0x80 +# define SEG_GRAN_BYTE 0x00 +# define SEG_GRAN_4KBYTE 0x80 + +#define SEG_SIZE_D_B_MASK 0x40 +# define SEG_DB_16BIT 0x00 +# define SEG_DB_32BIT 0x40 + +#define SEG_SIZE_L_MASK 0x20 +# define SEG_L_64BIT 0x20 +# define SEG_L_32BIT 0x00 + +#define SEG_SIZE_AVL_MASK 0x10 + +#define SEG_SIZE_LIM_19_16_MASK 0x0f + + +/* +** System-segment and gate-descriptor types +** +** IA-32 V3, page 3-15. +*/ + // type 0: reserved +#define SEG_SYS_16BIT_TSS_AVAIL 0x1 +#define SEG_SYS_LDT 0x2 +#define SEG_SYS_16BIT_TSS_BUSY 0x3 +#define SEG_SYS_16BIT_CALL_GATE 0x4 +#define SEG_SYS_TASK_GATE 0x5 +#define SEG_SYS_16BIT_INT_GATE 0x6 +#define SEG_SYS_16BIT_TRAP_GATE 0x7 + // type 8: reserved +#define SEG_SYS_32BIT_TSS_AVAIL 0x9 + // type A: reserved +#define SEG_SYS_32BIT_TSS_BUSY 0xb +#define SEG_SYS_32BIT_CALL_GATE 0xc + // type D: reserved +#define SEG_SYS_32BIT_INT_GATE 0xe +#define SEG_SYS_32BIT_TRAP_GATE 0xf + +/* +** IDT Descriptors +** +** IA-32 V3, page 5-13. +** +** All have a segment selector in bytes 2 and 3; Task Gate descriptors +** have bytes 0, 1, 4, 6, and 7 reserved; others have bytes 0, 1, 6, +** and 7 devoted to the 16 bits of the Offset, with the low nybble of +** byte 4 reserved. +*/ +#define IDT_PRESENT 0x8000 +#define IDT_DPL_MASK 0x6000 +# define IDT_DPL_0 0x0000 +# define IDT_DPL_1 0x2000 +# define IDT_DPL_2 0x4000 +# define IDT_DPL_3 0x6000 +#define IDT_GATE_TYPE 0x0f00 +# define IDT_TASK_GATE 0x0500 +# define IDT_INT16_GATE 0x0600 +# define IDT_INT32_GATE 0x0e00 +# define IDT_TRAP16_GATE 0x0700 +# define IDT_TRAP32_GATE 0x0f00 + +/* +** Interrupt vectors +*/ + +// predefined by the architecture +#define VEC_DIVIDE_ERROR 0x00 +#define VEC_DEBUG_EXCEPTION 0x01 +#define VEC_NMI_INTERRUPT 0x02 +#define VEC_BREAKPOINT 0x03 +#define VEC_OVERFLOW 0x04 +#define VEC_BOUND_RANGE_EXCEEDED 0x05 +#define VEC_INVALID_OPCODE 0x06 +#define VEC_DEVICE_NOT_AVAILABLE 0x07 +#define VEC_DOUBLE_FAULT 0x08 +#define VEC_COPROCESSOR_OVERRUN 0x09 +#define VEC_INVALID_TSS 0x0a +#define VEC_SEGMENT_NOT_PRESENT 0x0b +#define VEC_STACK_FAULT 0x0c +#define VEC_GENERAL_PROTECTION 0x0d +#define VEC_PAGE_FAULT 0x0e +// 0x0f is reserved - unused +#define VEC_FPU_ERROR 0x10 +#define VEC_ALIGNMENT_CHECK 0x11 +#define VEC_MACHINE_CHECK 0x12 +#define VEC_SIMD_FP_EXCEPTION 0x13 +#define VEC_VIRT_EXCEPTION 0x14 +#define VEC_CTRL_PROT_EXCEPTION 0x15 +// 0x16 through 0x1f are reserved + +// 0x20 through 0xff are user-defined, non-reserved + +// IRQ0 through IRQ15 will use vectors 0x20 through 0x2f +#define VEC_TIMER 0x20 +#define VEC_KBD 0x21 +#define VEC_COM2 0x23 +#define VEC_COM1 0x24 +#define VEC_PARALLEL 0x25 +#define VEC_FLOPPY 0x26 +#define VEC_MYSTERY 0x27 +#define VEC_MOUSE 0x2c + +#endif diff --git a/include/x86/bios.h b/include/x86/bios.h new file mode 100644 index 0000000..a19e570 --- /dev/null +++ b/include/x86/bios.h @@ -0,0 +1,73 @@ +/* +** @file bios.h +** +** @author Warren R. Carithers +** +** BIOS-related declarations +*/ + +#ifndef BIOS_H_ +#define BIOS_H_ + +/* +** BIOS-related memory addresses +*/ + +#define BIOS_BDA 0x0400 + +/* +** Selected BIOS interrupt numbers +*/ + +#define BIOS_TIMER 0x08 +#define BIOS_KBD 0x09 +#define BIOS_VIDEO 0x10 +#define BIOS_EQUIP 0x11 +#define BIOS_MSIZ 0x12 +#define BIOS_DISK 0x13 +#define BIOS_SERIAL 0x14 +#define BIOS_MISC 0x15 +#define BIOS_KBDSVC 0x16 +#define BIOS_PRTSVC 0x17 +#define BIOS_BOOT 0x19 +#define BIOS_RTCPCI 0x1a + +// BIOS video commands (AH) +#define BV_W_ADV 0x0e + +// BIOS disk commands (AH) +#define BD_RESET 0x00 +#define BD_CHECK 0x01 +#define BD_RDSECT 0x02 +#define BD_WRSECT 0x03 +#define BD_PARAMS 0x08 + +// BIOS disk commands with parameters (AX) +#define BD_READ(n) ((BD_RDSECT << 8) | (n)) +#define BD_READ1 0x0201 + +// CMOS ports (used for masking NMIs) +#define CMOS_ADDR 0x70 +#define CMOS_DATA 0x71 + +// important related commands +#define NMI_ENABLE 0x00 +#define NMI_DISABLE 0x80 + +/* +** Physical Memory Map Table (0000:2D00 - 0000:7c00) +** +** Primarily used with the BIOS_MISC interrupt +*/ +#define MMAP_SEG 0x02D0 +#define MMAP_DISP 0x0000 +#define MMAP_ADDR ((MMAP_SEG << 4) + MMAP_DISP) +#define MMAP_SECTORS 0x0a + +#define MMAP_ENT 24 /* bytes per entry */ +#define MMAP_MAX_ENTS (BOOT_ADDR - MMAP_ADDR - 4) / 24 + +#define MMAP_CODE 0xE820 /* int 0x15 code */ +#define MMAP_MAGIC_NUM 0x534D4150 /* for 0xE820 interrupt */ + +#endif diff --git a/include/x86/ops.h b/include/x86/ops.h new file mode 100644 index 0000000..ad795b9 --- /dev/null +++ b/include/x86/ops.h @@ -0,0 +1,443 @@ +/** +** @file ops.h +** +** @author Warren R. Carithers +** +** @brief Inline escapes to assembly for efficiency +** +** Inspiration from: +** Martins Mozeiko, https://gist.github.com/mmozeiko/f68ad2546bd6ab953315 +** MIT's xv6, https://github.com/mit-pdos/xv6-public +** +** Note: normally, GCC doesn't inline unless the optimization level is +** over 1. This can be forced by adding +** +** __attribute__((always_inline)) +** +** after the parameter list on each declaration. This is enabled by +** defining the compile-time CPP symbol FORCE_INLINING. +*/ + +#ifndef OPS_H_ +#define OPS_H_ + +#include + +#ifndef ASM_SRC + +// control "forced" inlining +#ifdef FORCE_INLINING +#define OPSINLINED __attribute__((always_inline)) +#else +#define OPSINLINED /* no-op */ +#endif /* FORCE_INLINING */ + +/**************************** +** Data movement +****************************/ + +/** +** Block move functions +** +** Variations: movsb(), movsl(), movsq() +** +** Description: Copy from source buffer to destination buffer +** +** @param dst Destination buffer +** @param src Source buffer +** @param len Byte count +*/ +static inline void +movsb( void* dst, const void* src, uint32_t len ) OPSINLINED +{ + __asm__ __volatile__( "cld; rep movsb" + : "+D"(dst), "+S"(src), "+c"(len) + : : "memory" ); +} + +static inline void +movsw( void* dst, const void* src, uint32_t len ) OPSINLINED +{ + __asm__ __volatile__( "cld; rep movsw" + : "+D"(dst), "+S"(src), "+c"(len) + : : "memory" ); +} + +static inline void +movsl( void* dst, const void* src, uint32_t len ) OPSINLINED +{ + __asm__ __volatile__( "cld; rep movsl" + : "+D"(dst), "+S"(src), "+c"(len) + : : "memory" ); +} + +static inline void +movsq( void* dst, const void* src, uint32_t len ) OPSINLINED +{ + __asm__ __volatile__( "cld; rep movsq" + : "+D"(dst), "+S"(src), "+c"(len) + : : "memory" ); +} + +/** +** Block store functions +** +** Variations: stosb(), stosw(), stosl() +** +** Description: Store a specific value into destination buffer +** +** @param dst Destination buffer +** @param val Data to copy +** @param len Byte count +*/ +static inline void +stosb( void *dst, uint8_t val, uint32_t len ) OPSINLINED +{ + __asm__ __volatile__( "cld; rep stosb" + : "=D" (dst), "=c" (len) + : "0" (dst), "1" (len), "a" (val) + : "memory", "cc" ); +} + +static inline void +stosw( void *dst, uint16_t val, uint32_t len ) OPSINLINED +{ + __asm__ __volatile__( "cld; rep stos2" + : "=D" (dst), "=c" (len) + : "0" (dst), "1" (len), "a" (val) + : "memory", "cc" ); +} + +static inline void +stosl( void *dst, uint32_t val, uint32_t len ) OPSINLINED +{ + __asm__ __volatile__( "cld; rep stosl" + : "=D" (dst), "=c" (len) + : "0" (dst), "1" (len), "a" (val) + : "memory", "cc" ); +} + +/**************************** +** Special register access +****************************/ + +/** +** Register read functions +** +** Variations: r_cr0(), r_cr2(), r_cr3(), r_cr4(), r_eflags(), +** r_ebp(), r_esp() +** +** Description: Reads the register indicated by its name +** +** @return Contents of the register +*/ +static inline uint32_t +r_cr0( void ) OPSINLINED +{ + uint32_t val; + __asm__ __volatile__( "movl %%cr0,%0" : "=r" (val) ); + return val; +} + +static inline uint32_t +r_cr2( void ) OPSINLINED +{ + uint32_t val; + __asm__ __volatile__( "movl %%cr2,%0" : "=r" (val) ); + return val; +} + +static inline uint32_t +r_cr3( void ) OPSINLINED +{ + uint32_t val; + __asm__ __volatile__( "movl %%cr3,%0" : "=r" (val) ); + return val; +} + +static inline uint32_t +r_cr4( void ) OPSINLINED +{ + uint32_t val; + __asm__ __volatile__( "movl %%cr4,%0" : "=r" (val) ); + return val; +} + +static inline uint32_t +r_eflags(void) OPSINLINED +{ + uint32_t val; + __asm__ __volatile__( "pushfl; popl %0" : "=r" (val) ); + return val; +} + +static inline uint32_t +r_ebp(void) OPSINLINED +{ + uint32_t val; + __asm__ __volatile__( "movl %%ebp,%0" : "=r" (val) ); + return val; +} + +static inline uint32_t +r_esp(void) OPSINLINED +{ + uint32_t val; + __asm__ __volatile__( "movl %%esp,%0" : "=r" (val) ); + return val; +} + +/** +** Register write functions +** +** Variations: w_cr0(), w_cr2(), w_cr3(), w_cr4(), w_eflags() +** +** Description: Writes a value into the CR indicated by its name +*/ +static inline void +w_cr0( uint32_t val ) OPSINLINED +{ + __asm__ __volatile__( "movl %0,%%cr0" : : "r" (val) ); +} + +static inline void +w_cr2( uint32_t val ) OPSINLINED +{ + __asm__ __volatile__( "movl %0,%%cr2" : : "r" (val) ); +} + +static inline void +w_cr3( uint32_t val ) OPSINLINED +{ + __asm__ __volatile__( "movl %0,%%cr3" : : "r" (val) ); +} + +static inline void +w_cr4( uint32_t val ) OPSINLINED +{ + __asm__ __volatile__( "movl %0,%%cr4" : : "r" (val) ); +} + +static inline void +w_eflags(uint32_t eflags) OPSINLINED +{ + __asm__ __volatile__( "pushl %0; popfl" : : "r" (eflags) ); +} + +/** +** Descriptor table load functions +** +** Variations: w_gdt(), w_idt() +** +** Description: Load an address into the specified processor register +** +** @param addr The value to be loaded into the register +*/ +static inline void +w_gdt( void *addr ) OPSINLINED +{ + __asm__ __volatile__( "lgdt (%0)" : : "r" (addr) ); +} + +static inline void +w_idt( void *addr ) OPSINLINED +{ + __asm__ __volatile__( "lidt (%0)" : : "r" (addr) ); +} + +/** +** CPU ID access +** +** Description: Retrieve CPUID information +** +** @param op Value to be placed into %eax for the operation +** @param ap Pointer to where %eax contents should be saved, or NULL +** @param bp Pointer to where %ebx contents should be saved, or NULL +** @param cp Pointer to where %ecx contents should be saved, or NULL +** @param dp Pointer to where %edx contents should be saved, or NULL +*/ +static inline void +cpuid( uint32_t op, uint32_t *ap, uint32_t *bp, + uint32_t *cp, uint32_t *dp ) OPSINLINED +{ + uint32_t eax, ebx, ecx, edx; + __asm__ __volatile__( "cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "a" (op) ); + + if( ap ) *ap = eax; + if( bp ) *bp = ebx; + if( cp ) *cp = ecx; + if( dp ) *dp = edx; +} + +/**************************** +** TLB management +****************************/ + +/** +** TLB invalidation for one page +** +** Description: Invalidate the TLB entry for an address +** +** @param addr An address within the page to be flushed +*/ +static inline void +invlpg( uint32_t addr ) OPSINLINED +{ + __asm__ __volatile__( "invlpg (%0)" : : "r" (addr) : "memory" ); +} + +/** +** TLB invalidation for all pages +** +** Description: Flush all entries from the TLB +** +** We do this by changing CR3. +*/ +static inline void +flushtlb( void ) OPSINLINED +{ + uint32_t cr3; + __asm__ __volatile__( "movl %%cr3,%0" : "=r" (cr3) ); + __asm__ __volatile__( "movl %0,%%cr2" : : "r" (cr3) ); +} + +/**************************** +** I/O instructions +****************************/ + +/** +** Name: inN +** +** Variations: inb(), inw(), inl() +** +** Description: Read some amount of data from the supplied I/O port +** +** @param port The i/o port to read from +** +** @return The data read from the specified port +*/ +static inline uint8_t +inb( int port ) OPSINLINED +{ + uint8_t data; + __asm__ __volatile__( "inb %w1,%0" : "=a" (data) : "d" (port) ); + return data; +} + +static inline uint16_t +inw( int port ) OPSINLINED +{ + uint16_t data; + __asm__ __volatile__( "inw %w1,%0" : "=a" (data) : "d" (port) ); + return data; +} + +static inline uint32_t +inl( int port ) OPSINLINED +{ + uint32_t data; + __asm__ __volatile__( "inl %w1,%0" : "=a" (data) : "d" (port) ); + return data; +} + +/** +** Name: outN +** +** Variations: outb(), outw(), outl() +** +** Description: Write some data to the specified I/O port +** +** @param port The i/o port to write to +** @param data The data to be written to the port +** +** @return The data read from the specified port +*/ +static inline void +outb( int port, uint8_t data ) OPSINLINED +{ + __asm__ __volatile__( "outb %0,%w1" : : "a" (data), "d" (port) ); +} + +static inline void +outw( int port, uint16_t data ) OPSINLINED +{ + __asm__ __volatile__( "outw %0,%w1" : : "a" (data), "d" (port) ); +} + +static inline void +outl( int port, uint32_t data ) OPSINLINED +{ + __asm__ __volatile__( "outl %0,%w1" : : "a" (data), "d" (port) ); +} + +/**************************** +** Miscellaneous instructions +****************************/ + +/** +** Name: breakpoint +** +** Description: Cause a breakpoint interrupt for debugging purposes +*/ +static inline void +breakpoint( void ) OPSINLINED +{ + __asm__ __volatile__( "int3" ); +} + +/** +** Name: get_ra +** +** Description: Get the return address for the calling function +** (i.e., where whoever called us will go back to) +** +** @return The address the calling routine will return to as a uint32_t +*/ +static inline uint32_t +get_ra( void ) OPSINLINED +{ + uint32_t val; + __asm__ __volatile__( "movl 4(%%ebp),%0" : "=r" (val) ); + return val; +} + +/** +** Name: ev_wait +** +** Description: Pause until something happens +*/ +static inline void +ev_wait( void ) OPSINLINED +{ + __asm__ __volatile__( "sti ; hlt" ); +} + + +/** +** Name: xchgl +** +** Description: Perform an atomic exchange with memory +** +** @param addr Memory location to be modified +** @param data Data to exchange +** +** @return The old contents of the memory location +*/ +static inline uint32_t +xchgl( volatile uint32_t *addr, uint32_t data ) OPSINLINED +{ + uint32_t old; + + // + indicates a read-modify-write operand + __asm__ __volatile__( "lock; xchgl %0, %1" + : "+m" (*addr), "=a" (old) + : "1" (data) + : "cc"); + return old; +} + +#endif /* !ASM_SRC */ + +#endif diff --git a/include/x86/pic.h b/include/x86/pic.h new file mode 100644 index 0000000..d4fa93b --- /dev/null +++ b/include/x86/pic.h @@ -0,0 +1,139 @@ +/** +** @file pic.h +** +** @author Warren R. Carithers +** @author K. Reek +** +** Definitions of constants and macros for the Intel 8259 Programmable +** Interrupt Controller. +** +*/ + +#ifndef X86PIC_H_ +#define X86PIC_H_ + +/* +** Our expected configuration is two PICs, with the secondary connected +** through the IRQ2 pin of the primary. +*/ + +/* +** Port addresses for the command port and interrupt mask register port +** for both the primary and secondary PICs. +*/ +#define PIC1_CMD 0x20 // primary command +#define PIC1_DATA (PIC1_CMD + 1) // primary data / int mask register +#define PIC2_CMD 0xA0 // secondary command +#define PIC2_DATA (PIC2_CMD + 1) // secondary data / int mask register + +/* +** Initialization Command Word (ICW) definitions +** +** Initialization sequence: +** ICW1 Init command is sent to each command port. +** ICW2 vector commands are sent to the data ports. +** If "cascade mode" was selected, send ICW3 commands to the data ports. +** If "need ICW4" was selected, send ICW4 commands to the data ports. +** +** Following that sequence, the PIC is ready to accept interrupts; +** it will also accept Output Command Words (OCWs) to the data ports. +** +** PIC1_* defines are intended for the primary PIC +** PIC2_* defines are intended for the secondary PIC +** PIC_* defines are sent to both PICs +*/ + +/* +** ICW1: initialization, send to command port +*/ +#define PIC_CW1_INIT 0x10 // start initialization sequence +#define PIC_CW1_NEED4 0x01 // ICW4 will also be set +#define PIC_CW1_SINGLE 0x02 // select single (vs. cascade) mode +#define PIC_CW1_INTVAL 0x04 // set call interval to 4 (vs. 8) +#define PIC_CW1_LEVEL 0x08 // use level-triggered mode (vs. edge) + +/* +** ICW2: interrupt vector base offsets, send to data port +*/ +#define PIC1_CW2_VECBASE 0x20 // IRQ0 int vector number +#define PIC2_CW2_VECBASE 0x28 // IRQ8 int vector number + +/* +** ICW3: secondary::primary attachment, send to data port +*/ +#define PIC1_CW3_SEC_IRQ2 0x04 // bit mask: secondary is on pin 2 +#define PIC2_CW3_SEC_ID 0x02 // integer: secondary id + +/* +** ICW4: operating mode, send to data port +*/ +#define PIC_CW4_PM86 0x01 // 8086 mode (vs. 8080/8085) +#define PIC_CW4_AUTOEOI 0x02 // do auto eoi's +#define PIC_CW4_UNBUF 0x00 // unbuffered mode +#define PIC_CW4_SEC_BUF 0x08 // put secondary in buffered mode +#define PIC_CW4_PRI_BUF 0x0C // put primary in buffered mode +#define PIC_CW4_SFNMODE 0x10 // "special fully nested" mode + +/* +** Operation Control Words (OCWs) +** +** After the init sequence, can send these +*/ + +/* +** OCW1: interrupt mask; send to data port +*/ +#define PIC_MASK_NONE 0x00 // allow all interrupts +#define PIC_MASK_NO_IRQ0 0x01 // prevent IRQ0 interrupts +#define PIC_MASK_NO_IRQ1 0x02 // prevent IRQ1 interrupts +#define PIC_MASK_NO_IRQ2 0x04 // prevent IRQ2 interrupts +#define PIC_MASK_NO_IRQ3 0x08 // prevent IRQ3 interrupts +#define PIC_MASK_NO_IRQ4 0x10 // prevent IRQ4 interrupts +#define PIC_MASK_NO_IRQ5 0x20 // prevent IRQ5 interrupts +#define PIC_MASK_NO_IRQ6 0x40 // prevent IRQ6 interrupts +#define PIC_MASK_NO_IRQ7 0x80 // prevent IRQ7 interrupts +#define PIC_MASK_ALL 0xff // prevent all interrupts + +/* +** OCW2: EOI control, interrupt level; send to command port +*/ +#define PIC_LVL_0 0x00 // act on IRQ level 0 +#define PIC_LVL_1 0x01 // act on IRQ level 1 +#define PIC_LVL_2 0x02 // act on IRQ level 2 +#define PIC_LVL_3 0x03 // act on IRQ level 3 +#define PIC_LVL_4 0x04 // act on IRQ level 4 +#define PIC_LVL_5 0x05 // act on IRQ level 5 +#define PIC_LVL_6 0x06 // act on IRQ level 6 +#define PIC_LVL_7 0x07 // act on IRQ level 7 + +#define PIC_EOI_NON_SPEC 0x20 // non-specific EOI command +# define PIC_EOI PIC_EOI_NON_SPEC + +#define PIC_EOI_SPEC 0x60 // specific EOI command +# define PIC_SEOI PIC_EOI_SPEC +# define PIC_SEOI_LVL0 (PIC_EOI_SPEC | PIC_LVL_0) +# define PIC_SEOI_LVL1 (PIC_EOI_SPEC | PIC_LVL_1) +# define PIC_SEOI_LVL2 (PIC_EOI_SPEC | PIC_LVL_2) +# define PIC_SEOI_LVL3 (PIC_EOI_SPEC | PIC_LVL_3) +# define PIC_SEOI_LVL4 (PIC_EOI_SPEC | PIC_LVL_4) +# define PIC_SEOI_LVL5 (PIC_EOI_SPEC | PIC_LVL_5) +# define PIC_SEOI_LVL6 (PIC_EOI_SPEC | PIC_LVL_6) +# define PIC_SEOI_LVL7 (PIC_EOI_SPEC | PIC_LVL_7) + +#define PIC_EOI_ROT_NONSP 0xa0 // rotate on non-spec EOI cmd +#define PIC_EOI_SET_ROT_AUTO 0x80 // set "rotate in auto EOI mode" +#define PIC_EOI_CLR_ROT_AUTO 0x00 // clear "rotate in auto EOI mode" +#define PIC_EOI_ROT_SPEC 0xe0 // rotate on spec EOI cmd (+ level) +#define PIC_EOI_SET_PRIO 0xc0 // set priority (+ level) +#define PIC_EOI_NOP 0x40 // no operation + +/* +** OCW3: read requests, special mask mode; send to command port +*/ +#define PIC_READIRR 0x0a // read the IR register +#define PIC_READISR 0x0b // read the IS register +#define PIC_POLL 0x0c // poll +#define PIC_MASK_RESET 0x48 // reset special mask mode +#define PIC_MASK_SET 0x68 // set special mask mode + +#endif diff --git a/include/x86/pit.h b/include/x86/pit.h new file mode 100644 index 0000000..269fcec --- /dev/null +++ b/include/x86/pit.h @@ -0,0 +1,82 @@ +/* +** @file pit.h +** +** @author Warren R. Carithers +** @author K. Reek +** +** Definitions of constants and macros for the +** Intel 8254 Programmable Interval Timer +** +*/ + +#ifndef X86PIT_H_ +#define X86PIT_H_ + + +/* +** Hardware timer (Intel 8254 Programmable Interval Timer) +** +** Control word layout: +** +** Bit 7 6 | 5 4 | 3 2 1 | 0 +** Field SC1 SC0|RW1 RW0|M2 M1 M0 |BCD +** +** SC - select counter +** RW - read/write +** M - mode +** BCD - binary or BCD counter +*/ + +/* Frequency settings */ +#define PIT_DEFAULT_TICKS_PER_SECOND 18 // actually 18.2065Hz +#define PIT_DEFAULT_MS_PER_TICK (1000/PIT_DEFAULT_TICKS_PER_SECOND) +#define PIT_FREQ 1193182 // clock cycles/sec + +/* Port assignments */ +#define PIT_BASE_PORT 0x40 // I/O port for the timer +# define PIT_0_PORT (PIT_BASE_PORT) +# define PIT_1_PORT (PIT_BASE_PORT+1) +# define PIT_2_PORT (PIT_BASE_PORT+2) +# define PIT_CONTROL_PORT (PIT_BASE_PORT+3) + +/* BCD field */ +#define PIT_USE_DECIMAL 0x00 // 16-bit binary counter (default) +#define PIT_USE_BCD 0x01 // BCD counter + +/* Timer modes */ +#define PIT_MODE_0 0x00 // int on terminal count +#define PIT_MODE_1 0x02 // one-shot +#define PIT_MODE_2 0x04 // divide-by-N +#define PIT_MODE_3 0x06 // square-wave +#define PIT_MODE_4 0x08 // software strobe +#define PIT_MODE_5 0x0a // hardware strobe + +/* Timer 0 settings */ +#define PIT_0_SELECT 0x00 // select timer 0 +#define PIT_0_LOAD 0x30 // load LSB, then MSB +#define PIT_0_NDIV PIT_MODE_2 // divide-by-N counter +#define PIT_0_SQUARE PIT_MODE_3 // square-wave mode +#define PIT_0_ENDSIGNAL 0x00 // assert OUT at end of count + +/* Timer 1 settings */ +#define PIT_1_SELECT 0x40 // select timer 1 +#define PIT_1_READ 0x30 // read/load LSB then MSB +#define PIT_1_RATE 0x06 // square-wave, for USART + +/* Timer 2 settings */ +#define PIT_2_SELECT 0x80 // select timer 1 +#define PIT_2_READ 0x30 // read/load LSB then MSB +#define PIT_2_RATE 0x06 // square-wave, for USART + +/* Timer read-back */ +#define PIT_READBACK 0xc0 // perform a read-back +#define PIT_RB_NOT_COUNT 0x20 // don't latch the count +#define PIT_RB_NOT_STATUS 0x10 // don't latch the status +#define PIT_RB_CHAN_2 0x08 // read back channel 2 +#define PIT_RB_CHAN_1 0x04 // read back channel 1 +#define PIT_RB_CHAN_0 0x02 // read back channel 0 +#define PIT_RB_ACCESS_MASK 0x30 // access mode field +#define PIT_RB_OP_MASK 0x0e // oper mode field +#define PIT_RB_BCD_MASK 0x01 // BCD mode field + +#endif diff --git a/include/x86/uart.h b/include/x86/uart.h new file mode 100644 index 0000000..0c6194b --- /dev/null +++ b/include/x86/uart.h @@ -0,0 +1,349 @@ +/* +** @file uart.h +** +** @author M. Reek +** @authors K. Reek, Warren R. Carithers +** +** Definitions for a 16540/16550 compatible UART. Definitions are taken +** from datasheets for the National Semiconductor INS8250, NS16450, and +** NS16550 UART chips, and the PC87309 Super I/O legacy peripheral chip. +** +** The naming convention is UAx_yyy_zzzzz. "x" is either 4 or 5 (see below), +** "yyy" is the name of the register to which this value applies, and +** "zzzzz" is the name of the value or field. +** +** The UA4 prefix denotes 16540 compatible functions, available in both +** chips. The UA5 prefix denotes 16550-only functions (primarily the FIFOs). +** +** For many items there are two names: one short one that matches the name +** in the chip manual, and another that is more readable. +*/ + +#ifndef UART_H +#define UART_H + +/********************************************************************* +***************************** I/O PORTS ****************************** +*********************************************************************/ + +/* +** Base port number assigned to the device +*/ +#define UA4_COM1_PORT 0x3f8 +#define UA4_COM2_PORT 0x2f8 +#define UA4_COM3_PORT 0x3e8 +#define UA4_COM4_PORT 0x2e8 + +// short name for the one we'll use +#define UA4_PORT UA4_COM1_PORT +#define UA5_PORT UA4_COM1_PORT + +/* +** Registers +** +** The 164x0 chips have the following registers. The (RO) and (WO) +** suffixes indicate read-only and write-only access. +** +** Index Register(s) +** ===== ========================================= +** 0 Receiver Data (RO), Transmitter Data (WO) +** 1 Interrupt Enable +** 2 Interrupt ID (RO), FIFO Control (WO) +** 3 Line Control, Divisor Latch +** 4 Modem Control +** 5 Line Status +** 6 Modem Status +** 7 Scratch +** +** Registers indices are relative to the base I/O port for the +** specific UART port being used (e.g., for COM1, the port addresses +** are 0x3f8 through 0x3ff). When two registers share a port and have +** different access methods (RO vs. WO), a read from the port accesses +** the RO register and a write to the port access the WO register. +** +** The Line Control and Divisor Latch registers are accessed by writing +** a byte to the port; the high-order bit determines which register is +** accessed (0 selects Line Control, 1 selects Divisor Latch), with the +** remaining bits selecting fields within the indicated register. +*/ + +/* +** Receiver Data Register (read-only) +*/ +#define UA4_RXD (UA4_PORT+0) +# define UA4_RX_DATA UA4_RXD + +/* +** Transmitter Data Register (write-only) +*/ +#define UA4_TXD (UA4_PORT+0) +# define UA4_TX_DATA UA4_TXD + +/* +** Interrupt Enable Register +*/ +#define UA4_IER (UA4_PORT+1) +# define UA4_INT_ENABLE_REG UA4_IER + +// fields +#define UA4_IER_RX_IE 0x01 // Rcvr High-Data-Level Int Enable +#define UA4_IER_TX_IE 0x02 // Xmitter Low-data-level Int Enable +#define UA4_IER_LS_IE 0x04 // Line Status Int Enable +#define UA4_IER_MS_IE 0x08 // Modem Status Int Enable + +// aliases +#define UA4_IER_RX_INT_ENABLE UA4_IER_RX_IE +#define UA4_IER_TX_INT_ENABLE UA4_IER_TX_IE +#define UA4_IER_LINE_STATUS_INT_ENABLE UA4_IER_LS_IE +#define UA4_IER_MODEM_STATUS_INT_ENABLE UA4_IER_MS_IE + +/* +** Interrupt Identification Register (read-only) +** +** a.k.a. Event Identification Register +*/ +#define UA4_IIR (UA4_PORT+2) +# define UA4_EVENT_ID UA4_IIR + +// fields +#define UA4_IIR_IPF 0x01 // Interrupt Pending flag + +#define UA4_IIR_IPR_MASK 0x06 // Interrupt Priority mask +# define UA4_IIR_IPR0_MASK 0x02 // IPR bit 0 mask +# define UA4_IIR_IPR1_MASK 0x04 // IPR bit 1 mask + +#define UA5_IIR_RXFT 0x08 // RX_FIFO Timeout +#define UA5_IIR_FEN0 0x40 // FIFOs Enabled +#define UA5_IIR_FEN1 0x80 // FIFOs Enabled + +// aliases +#define UA4_IIR_INT_PENDING UA4_IIR_IPF +#define UA4_IIR_INT_PRIORITY UA4_IIR_IPR +#define UA5_IIR_RX_FIFO_TIMEOUT UA5_IIR_RXFT +#define UA5_IIR_FIFO_ENABLED_0 UA5_IIR_FEN0 +#define UA5_IIR_FIFO_ENABLED_1 UA5_IIR_FEN1 + +// IIR interrupt priorities (four-bit values) +#define UA4_IIR_INT_PRI_MASK 0x0f // Mask for extracting int priority +# define UA4_IIR_NO_INT 0x01 // no interrupt +# define UA4_IIR_LINE_STATUS 0x06 // line status interrupt +# define UA4_IIR_RX 0x04 // Receiver High Data Level +# define UA5_IIR_RX_FIFO 0x0c // Receiver FIFO timeout (16550) +# define UA4_IIR_TX 0x02 // Transmitter Low Data level +# define UA4_IIR_MODEM_STATUS 0x00 // Modem Status + +// aliases +#define UA4_IIR_NO_INT_PENDING UA4_IIR_NO_INT +#define UA4_IIR_LINE_STATUS_INT_PENDING UA4_IIR_LINE_STATUS +#define UA4_IIR_RX_INT_PENDING UA4_IIR_RX +#define UA5_IIR_RX_FIFO_TIMEOUT_INT_PENDING UA5_IIR_RX_FIFO +#define UA4_IIR_TX_INT_PENDING UA4_IIR_TX +#define UA4_IIR_MODEM_STATUS_INT_PENDING UA4_IIR_MODEM_STATUS + +/* +** FIFO Control Register (16550 only, write-only) +*/ +#define UA5_FCR (UA5_PORT+2) +# define UA5_FIFO_CTL UA5_FCR + +#define UA5_FCR_FIFO_RESET 0x00 // Reset the FIFO +#define UA5_FCR_FIFO_EN 0x01 // FIFO Enable +#define UA5_FCR_RXSR 0x02 // Receiver Soft Reset +#define UA5_FCR_TXSR 0x04 // Transmitter Soft Reset + +#define UA5_FCR_TXFT_MASK 0x30 // TX_FIFO threshold level mask +# define UA5_FCR_TXFT0_MASK 0x10 // TXFT bit 0 mask +# define UA5_FCR_TXFT1_MASK 0x20 // TXFT bit 1 mask +# define UA5_FCR_TX_FIFO_1 0x00 // 1 char +# define UA5_FCR_TX_FIFO_3 0x10 // 3 char +# define UA5_FCR_TX_FIFO_9 0x20 // 9 char +# define UA5_FCR_TX_FIFO_13 0x30 // 13 char + +#define UA5_FCR_RXFT_MASK 0xc0 // RX_FIFO threshold level mask +# define UA5_FCR_RXFT0_MASK 0x40 // RXFT bit 0 mask +# define UA5_FCR_RXFT1_MASK 0x80 // RXFT bit 1 mask +# define UA5_FCR_RX_FIFO_1 0x00 // 1 char +# define UA5_FCR_RX_FIFO_4 0x40 // 4 char +# define UA5_FCR_RX_FIFO_8 0x80 // 8 char +# define UA5_FCR_RX_FIFO_14 0xc0 // 14 char + +// aliases +#define UA5_FCR_FIFO_ENABLED UA5_FCR_FIFO_EN +#define UA5_FCR_RX_SOFT_RESET UA5_FCR_RXSR +#define UA5_FCR_TX_SOFT_RESET UA5_FCR_TXSR +#define UA5_FCR_TX_FIFO_1_CHAR UA5_FCR_TX_FIFO_1 +#define UA5_FCR_TX_FIFO_3_CHAR UA5_FCR_TX_FIFO_3 +#define UA5_FCR_TX_FIFO_9_CHAR UA5_FCR_TX_FIFO_9 +#define UA5_FCR_TX_FIFO_13_CHAR UA5_FCR_TX_FIFO_13 +#define UA5_FCR_RX_FIFO_1_CHAR UA5_FCR_RX_FIFO_1 +#define UA5_FCR_RX_FIFO_4_CHAR UA5_FCR_RX_FIFO_4 +#define UA5_FCR_RX_FIFO_8_CHAR UA5_FCR_RX_FIFO_8 +#define UA5_FCR_RX_FIFO_14_CHAR UA5_FCR_RX_FIFO_14 + +/* +** Line Control Register (available in all banks) +** +** Selected when bit 7 of the value written to the port is a 0. +*/ +#define UA4_LCR (UA4_PORT+3) +# define UA4_LINE_CTL UA4_LCR + +#define UA4_LCR_WLS_MASK 0x03 // Word Length Select mask +# define UA4_LCR_WLS0_MASK 0x01 // WLS bit 0 mask +# define UA4_LCR_WLS1_MASK 0x02 // WLS bit 1 mask +# define UA4_LCR_WLS_5 0x00 // 5 bits per char +# define UA4_LCR_WLS_6 0x01 // 6 bits per char +# define UA4_LCR_WLS_7 0x02 // 7 bits per char +# define UA4_LCR_WLS_8 0x03 // 8 bits per char + +#define UA4_LCR_STB 0x04 // Stop Bits +# define UA4_LCR_1_STOP_BIT 0x00 +# define UA4_LCR_2_STOP_BIT 0x04 + +#define UA4_LCR_PEN 0x08 // Parity Enable +#define UA4_LCR_EPS 0x10 // Even Parity Select +#define UA4_LCR_STKP 0x20 // Sticky Parity +# define UA4_LCR_NO_PARITY 0x00 +# define UA4_LCR_ODD_PARITY UA4_LCR_PEN +# define UA4_LCR_EVEN_PARITY (UA4_LCR_PEN|UA4_LCR_EPS) +# define UA4_LCR_PARITY_LOGIC_1 (UA4_LCR_PEN|UA4_LCR_STKP) +# define UA4_LCR_PARITY_LOGIC_0 (UA4_LCR_PEN|UA4_LCR_EPS|UA4_LCR_STKP) + +#define UA4_LCR_SBRK 0x40 // Set Break +#define UA4_LCR_DLAB 0x80 // Divisor Latch select bit + +// aliases +# define UA4_LCR_STOP_BITS UA4_LCR_STB +# define UA4_LCR_PARITY_ENABLE UA4_LCR_PEN +# define UA4_LCR_SET_BREAK UA4_LCR_SBRK +# define UA4_LCR_BANK_SELECT_ENABLE UA4_LCR_BKSE + +/* +** Divisor Latch Registers +** Divisor Latch Least Significant (DLL) +** Divisor Latch Most Significant (DLM) +** +** These contain the lower and upper halves of the 16-bit divisor for +** baud rate generation. +** +** Accessing them requires sending a command to LCR with the most +** significant bit (0x80, the DLAB field) set. This "unlocks" the +** Divisor Latch registers, which are accessed at UA4_PORT+0 and +** UA4_PORT+1 (i.e., in place of the RXD/TXD and IE registers). To +** "re-lock" the Divisor Latch registers, write a command byte to +** LCR with 0 in the DLAB bit. +*/ +#define UA4_DLL (UA4_PORT+0) // Divisor Latch (least sig.) +#define UA4_DLM (UA4_PORT+1) // Divisor Latch (most sig.) + +// aliases +#define UA4_DIVISOR_LATCH_LS UA4_DLL +#define UA4_DIVISOR_LATCH_MS UA4_DLM + +// Baud rate divisor high and low bytes +#define BAUD_HIGH_BYTE(x) (((x) >> 8) & 0xff) +#define BAUD_LOW_BYTE(x) ((x) & 0xff) + +// Baud rate divisors +#define DL_BAUD_50 2304 +#define DL_BAUD_75 1536 +#define DL_BAUD_110 1047 +#define DL_BAUD_150 768 +#define DL_BAUD_300 384 +#define DL_BAUD_600 192 +#define DL_BAUD_1200 96 +#define DL_BAUD_1800 64 +#define DL_BAUD_2000 58 +#define DL_BAUD_2400 48 +#define DL_BAUD_3600 32 +#define DL_BAUD_4800 24 +#define DL_BAUD_7200 16 +#define DL_BAUD_9600 12 +#define DL_BAUD_14400 8 +#define DL_BAUD_19200 6 +#define DL_BAUD_28800 4 +#define DL_BAUD_38400 3 +#define DL_BAUD_57600 2 +#define DL_BAUD_115200 1 + +/* +** Modem Control Register +*/ +#define UA4_MCR (UA4_PORT+4) +# define UA4_MODEM_CTL UA4_MCR + +#define UA4_MCR_DTR 0x01 // Data Terminal Ready +#define UA4_MCR_RTS 0x02 // Ready to Send +#define UA4_MCR_RILP 0x04 // Loopback Interrupt Request +#define UA4_MCR_ISEN 0x08 // Interrupt Signal Enable +#define UA4_MCR_DCDLP 0x08 // DCD Loopback +#define UA4_MCR_LOOP 0x10 // Loopback Enable + +// aliases +#define UA4_MCR_DATA_TERMINAL_READY UA4_MCR_DTR +#define UA4_MCR_READY_TO_SEND UA4_MCR_RTS +#define UA4_MCR_LOOPBACK_INT_REQ UA4_MCR_RILP +#define UA4_MCR_INT_SIGNAL_ENABLE UA4_MCR_ISEN +#define UA4_MCR_LOOPBACK_DCD UA4_MCR_DCDLP +#define UA4_MCR_LOOPBACK_ENABLE UA4_MCR_LOOP + +/* +** Line Status Register +*/ +#define UA4_LSR (UA4_PORT+5) +# define UA4_LINE_STATUS UA4_LSR + +#define UA4_LSR_RXDA 0x01 // Receiver Data Available +#define UA4_LSR_OE 0x02 // Overrun Error +#define UA4_LSR_PE 0x04 // Parity Error +#define UA4_LSR_FE 0x08 // Framing Error +#define UA4_LSR_BRK 0x10 // Break Event Detected +#define UA4_LSR_TXRDY 0x20 // Transmitter Ready +#define UA4_LSR_TXEMP 0x40 // Transmitter Empty +#define UA4_LSR_ER_INF 0x80 // Error in RX_FIFO + +// aliases +#define UA4_LSR_RX_DATA_AVAILABLE UA4_LSR_RXDA +#define UA4_LSR_OVERRUN_ERROR UA4_LSR_OE +#define UA4_LSR_PARITY_ERROR UA4_LSR_PE +#define UA4_LSR_FRAMING_ERROR UA4_LSR_FE +#define UA4_LSR_BREAK_DETECTED UA4_LSR_BRK +#define UA4_LSR_TX_READY UA4_LSR_TXRDY +#define UA4_LSR_TX_EMPTY UA4_LSR_TXEMP +#define UA4_LSR_RX_FIFO_ERROR UA4_LSR_ER_INF + +/* +** Modem Status Register +*/ +#define UA4_MSR (UA4_PORT+6) +# define UA4_MODEM_STATUS UA4_MSR + +#define UA4_MSR_DCTS 0x01 // Delta Clear to Send +#define UA4_MSR_DDSR 0x02 // Delta Data Set Ready +#define UA4_MSR_TERI 0x04 // Trailing Edge Ring Indicate +#define UA4_MSR_DDCD 0x08 // Delta Data Carrier Detect +#define UA4_MSR_CTS 0x10 // Clear to Send +#define UA4_MSR_DSR 0x20 // Data Set Ready +#define UA4_MSR_RI 0x40 // Ring Indicate +#define UA4_MSR_DCD 0x80 // Data Carrier Detect + +// aliases +#define UA4_MSR_DELTA_CLEAR_TO_SEND UA4_MSR_DCTS +#define UA4_MSR_DELTA_DATA_SET_READY UA4_MSR_DDSR +#define UA4_MSR_TRAILING_EDGE_RING UA4_MSR_TERI +#define UA4_MSR_DELTA_DATA_CARRIER_DETECT UA4_MSR_DDCD +#define UA4_MSR_CLEAR_TO_SEND UA4_MSR_CTS +#define UA4_MSR_DATA_SET_READY UA4_MSR_DSR +#define UA4_MSR_RING_INDICATE UA4_MSR_RI +#define UA4_MSR_DATA_CARRIER_DETECT UA4_MSR_DCD + +/* +** Scratch Register +** +** Not used by the UART; usable as a "scratchpad" register for +** temporary storage. +*/ +#define UA4_SCR (UA4_PORT+7) +# define UA4_SCRATCH UA4_UA5_SCR + +#endif /* uart.h */ diff --git a/kernel/Make.mk b/kernel/Make.mk new file mode 100644 index 0000000..0c9b507 --- /dev/null +++ b/kernel/Make.mk @@ -0,0 +1,66 @@ +# +# Makefile fragment for the kernel components of the system. +# +# Makefile fragment for the kernel component of the system. +# +# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level +# directory, and this will be pulled in automatically. +# + +SUBDIRS += kernel + +################### +# FILES SECTION # +################### + +BOOT_OBJ := $(patsubst %.c, $(BUILDDIR)/%.o, $(BOOT_SRC)) + +KERN_SRC := kernel/startup.S kernel/isrs.S \ + kernel/cio.c kernel/clock.c kernel/kernel.c kernel/kmem.c \ + kernel/list.c kernel/procs.c kernel/sio.c kernel/support.c \ + kernel/syscalls.c kernel/user.c kernel/vm.c kernel/vmtables.c + +KERN_OBJ := $(patsubst %.c, $(BUILDDIR)/%.o, $(KERN_SRC)) +KERN_OBJ := $(patsubst %.S, $(BUILDDIR)/%.o, $(KERN_OBJ)) + +KCFLAGS := -ggdb +KLDFLAGS := -T kernel/kernel.ld +KLIBS := -lkernel -lcommon + +################### +# RULES SECTION # +################### + +kernel: $(BUILDDIR)/kernel/kernel.b + +$(BUILDDIR)/kernel/%.o: kernel/%.c $(BUILDDIR)/.vars.CFLAGS + @mkdir -p $(@D) + $(CC) $(CFLAGS) $(KCFLAGS) -c -o $@ $< + +$(BUILDDIR)/kernel/%.o: kernel/%.S $(BUILDDIR)/.vars.CFLAGS + @mkdir -p $(@D) + $(CPP) $(CPPFLAGS) -o $(@D)/$*.s $< + $(AS) $(ASFLAGS) $(KCFLAGS) -o $@ $(@D)/$*.s -a=$(@D)/$*.lst + $(RM) -f $(@D)/$*.s + +$(BUILDDIR)/kernel/kernel: $(KERN_OBJ) + @mkdir -p $(@D) + $(LD) $(KLDFLAGS) $(LDFLAGS) -o $@ $(KERN_OBJ) $(KLIBS) + $(OBJDUMP) -S $@ > $@.asm + $(NM) -n $@ > $@.sym + $(READELF) -a $@ > $@.info + +$(BUILDDIR)/kernel/kernel.b: $(BUILDDIR)/kernel/kernel + $(LD) $(LDFLAGS) -o $(BUILDDIR)/kernel/kernel.b -s \ + --oformat binary -Ttext 0x10000 $(BUILDDIR)/kernel/kernel + +# some debugging assist rules +$(BUILDDIR)/kernel/%.i: kernel/%.c $(BUILDDIR)/.vars.CFLAGS + @mkdir -p $(@D) + $(CC) $(CFLAGS) $(KCFLAGS) -E -c $< > $(@D)/$*.i + +$(BUILDDIR)/kernel/%.dat: $(BUILDDIR)/kernel/%.o + @mkdir -p $(@D) + $(OBJCOPY) -S -O binary -j .data $< $@ + hexdump -C $@ > $(@D)/$*.hex + diff --git a/kernel/cio.c b/kernel/cio.c new file mode 100644 index 0000000..cfff543 --- /dev/null +++ b/kernel/cio.c @@ -0,0 +1,796 @@ +/* +** SCCS ID: @(#)cio.c 2.10 1/22/25 +** +** @file cio.c +** +** @author Warren R. Carithers +** +** Based on: c_io.c 1.13 (Ken Reek, Jon Coles, Warren R. Carithers) +** +** Console I/O routines +** +** This module implements a simple set of input and output routines +** for the console screen and keyboard on the machines in the DSL. +** Refer to the header file comments for complete details. +** +** Naming conventions: +** +** Externally-visible functions have names beginning with the +** characters "cio_". +** +*/ + +#include +#include +#include +#include +#include +#include + +/* +** Bit masks for the lower five and eight bits of a value +*/ +#define BMASK5 0x1f +#define BMASK8 0xff + +/* +** Video parameters +*/ +#define SCREEN_MIN_X 0 +#define SCREEN_MIN_Y 0 +#define SCREEN_X_SIZE 80 +#define SCREEN_Y_SIZE 25 +#define SCREEN_MAX_X ( SCREEN_X_SIZE - 1 ) +#define SCREEN_MAX_Y ( SCREEN_Y_SIZE - 1 ) + +/* +** Video state +*/ +static unsigned int scroll_min_x, scroll_min_y; +static unsigned int scroll_max_x, scroll_max_y; +static unsigned int curr_x, curr_y; +static unsigned int min_x, min_y; +static unsigned int max_x, max_y; + +// pointer to input notification function +static void (*notify)(int); + +#ifdef SA_DEBUG +#include +#define cio_putchar putchar +#define cio_puts(x) fputs( x, stdout ) +#endif + + +/* +** VGA definitions. +*/ + +// calculate the memory address of a specific character position +// within VGA memory +#define VIDEO_ADDR(x,y) ( unsigned short * ) \ + ( VID_BASE_ADDR + 2 * ( (y) * SCREEN_X_SIZE + (x) ) ) + +// port addresses +#define VGA_CTRL_IX_ADDR 0x3d4 +# define VGA_CTRL_CUR_HIGH 0x0e // cursor location, high byte +# define VGA_CTRL_CUR_LOW 0x0f // cursor location, low byte +#define VGA_CTRL_IX_DATA 0x3d5 + +// attribute bits +#define VGA_ATT_BBI 0x80 // blink, or background intensity +#define VGA_ATT_BGC 0x70 // background color +#define VGA_ATT_FICS 0x80 // foreground intensity or char font select +#define VGA_ATT_FGC 0x70 // foreground color + +// color selections +#define VGA_BG_BLACK 0x0000 // background colors +#define VGA_BG_BLUE 0x1000 +#define VGA_BG_GREEN 0x2000 +#define VGA_BG_CYAN 0x3000 +#define VGA_BG_RED 0x4000 +#define VGA_BG_MAGENTA 0x5000 +#define VGA_BG_BROWN 0x6000 +#define VGA_BG_WHITE 0x7000 + +#define VGA_FG_BLACK 0x0000 // foreground colors +#define VGA_FG_BLUE 0x0100 +#define VGA_FG_GREEN 0x0200 +#define VGA_FG_CYAN 0x0300 +#define VGA_FG_RED 0x0400 +#define VGA_FG_MAGENTA 0x0500 +#define VGA_FG_BROWN 0x0600 +#define VGA_FG_WHITE 0x0700 + +// color combinations +#define VGA_WHITE_ON_BLACK (VGA_FG_WHITE | VGA_BG_BLACK) +#define VGA_BLACK_ON_WHITE (VGA_FG_BLACK | VGA_BG_WHITE) + +/* +** Internal support routines. +*/ + +/* +** setcursor: set the cursor location (screen coordinates) +*/ +static void setcursor( void ) { + unsigned addr; + unsigned int y = curr_y; + + if( y > scroll_max_y ) { + y = scroll_max_y; + } + + addr = (unsigned)( y * SCREEN_X_SIZE + curr_x ); + + outb( VGA_CTRL_IX_ADDR, VGA_CTRL_CUR_HIGH ); + outb( VGA_CTRL_IX_DATA, ( addr >> 8 ) & BMASK8 ); + outb( VGA_CTRL_IX_ADDR, VGA_CTRL_CUR_LOW ); + outb( VGA_CTRL_IX_DATA, addr & BMASK8 ); +} + +/* +** putchar_at: physical output to the video memory +*/ +static void putchar_at( unsigned int x, unsigned int y, unsigned int c ) { + /* + ** If x or y is too big or small, don't do any output. + */ + if( x <= max_x && y <= max_y ) { + unsigned short *addr = VIDEO_ADDR( x, y ); + + /* + ** The character may have attributes associated with it; if + ** so, use those, otherwise use white on black. + */ + c &= 0xffff; // keep only the lower bytes + if( c > BMASK8 ) { + *addr = (unsigned short)c; + } else { + *addr = (unsigned short)c | VGA_WHITE_ON_BLACK; + } + } +} + +/* +** Globally-visible support routines. +*/ + +/* +** Set the scrolling region +*/ +void cio_setscroll( unsigned int s_min_x, unsigned int s_min_y, + unsigned int s_max_x, unsigned int s_max_y ) { + scroll_min_x = bound( min_x, s_min_x, max_x ); + scroll_min_y = bound( min_y, s_min_y, max_y ); + scroll_max_x = bound( scroll_min_x, s_max_x, max_x ); + scroll_max_y = bound( scroll_min_y, s_max_y, max_y ); + curr_x = scroll_min_x; + curr_y = scroll_min_y; + setcursor(); +} + +/* +** Cursor movement in the scroll region +*/ +void cio_moveto( unsigned int x, unsigned int y ) { + curr_x = bound( scroll_min_x, x + scroll_min_x, scroll_max_x ); + curr_y = bound( scroll_min_y, y + scroll_min_y, scroll_max_y ); + setcursor(); +} + +/* +** The putchar family +*/ +void cio_putchar_at( unsigned int x, unsigned int y, unsigned int c ) { + if( ( c & 0x7f ) == '\n' ) { + unsigned int limit; + + /* + ** If we're in the scroll region, don't let this loop + ** leave it. If we're not in the scroll region, don't + ** let this loop enter it. + */ + if( x > scroll_max_x ) { + limit = max_x; + } + else if( x >= scroll_min_x ) { + limit = scroll_max_x; + } + else { + limit = scroll_min_x - 1; + } + while( x <= limit ) { + putchar_at( x, y, ' ' ); + x += 1; + } + } + else { + putchar_at( x, y, c ); + } +} + +#ifndef SA_DEBUG +void cio_putchar( unsigned int c ) { + /* + ** If we're off the bottom of the screen, scroll the window. + */ + if( curr_y > scroll_max_y ) { + cio_scroll( curr_y - scroll_max_y ); + curr_y = scroll_max_y; + } + + switch( c & BMASK8 ) { + case '\n': + /* + ** Erase to the end of the line, then move to new line + ** (actual scroll is delayed until next output appears). + */ + while( curr_x <= scroll_max_x ) { + putchar_at( curr_x, curr_y, ' ' ); + curr_x += 1; + } + curr_x = scroll_min_x; + curr_y += 1; + break; + + case '\r': + curr_x = scroll_min_x; + break; + + default: + putchar_at( curr_x, curr_y, c ); + curr_x += 1; + if( curr_x > scroll_max_x ) { + curr_x = scroll_min_x; + curr_y += 1; + } + break; + } + setcursor(); +} +#endif + +/* +** The puts family +*/ +void cio_puts_at( unsigned int x, unsigned int y, const char *str ) { + unsigned int ch; + + while( (ch = *str++) != '\0' && x <= max_x ) { + cio_putchar_at( x, y, ch ); + x += 1; + } +} + +#ifndef SA_DEBUG +void cio_puts( const char *str ) { + unsigned int ch; + + while( (ch = *str++) != '\0' ) { + cio_putchar( ch ); + } +} +#endif + +/* +** Write a "sized" buffer (like cio_puts(), but no NUL) +*/ +void cio_write( const char *buf, int length ) { + for( int i = 0; i < length; ++i ) { + cio_putchar( buf[i] ); + } +} + +void cio_clearscroll( void ) { + unsigned int nchars = scroll_max_x - scroll_min_x + 1; + unsigned int l; + unsigned int c; + + for( l = scroll_min_y; l <= scroll_max_y; l += 1 ) { + unsigned short *to = VIDEO_ADDR( scroll_min_x, l ); + + for( c = 0; c < nchars; c += 1 ) { + *to++ = ' ' | 0x0700; + } + } +} + +void cio_clearscreen( void ) { + unsigned short *to = VIDEO_ADDR( min_x, min_y ); + unsigned int nchars = ( max_y - min_y + 1 ) * ( max_x - min_x + 1 ); + + while( nchars > 0 ) { + *to++ = ' ' | 0x0700; + nchars -= 1; + } +} + + +void cio_scroll( unsigned int lines ) { + unsigned short *from; + unsigned short *to; + int nchars = scroll_max_x - scroll_min_x + 1; + int line, c; + + /* + ** If # of lines is the whole scrolling region or more, just clear. + */ + if( lines > scroll_max_y - scroll_min_y ) { + cio_clearscroll(); + curr_x = scroll_min_x; + curr_y = scroll_min_y; + setcursor(); + return; + } + + /* + ** Must copy it line by line. + */ + for( line = scroll_min_y; line <= scroll_max_y - lines; line += 1 ) { + from = VIDEO_ADDR( scroll_min_x, line + lines ); + to = VIDEO_ADDR( scroll_min_x, line ); + for( c = 0; c < nchars; c += 1 ) { + *to++ = *from++; + } + } + + for( ; line <= scroll_max_y; line += 1 ) { + to = VIDEO_ADDR( scroll_min_x, line ); + for( c = 0; c < nchars; c += 1 ) { + *to++ = ' ' | 0x0700; + } + } +} + +static int mypad( int x, int y, int extra, int padchar ) { + while( extra > 0 ) { + if( x != -1 || y != -1 ) { + cio_putchar_at( x, y, padchar ); + x += 1; + } + else { + cio_putchar( padchar ); + } + extra -= 1; + } + return x; +} + +static int mypadstr( int x, int y, char *str, int len, int width, + int leftadjust, int padchar ) { + int extra; + + if( len < 0 ) { + len = strlen( str ); + } + extra = width - len; + if( extra > 0 && !leftadjust ) { + x = mypad( x, y, extra, padchar ); + } + if( x != -1 || y != -1 ) { + cio_puts_at( x, y, str ); + x += len; + } + else { + cio_puts( str ); + } + if( extra > 0 && leftadjust ) { + x = mypad( x, y, extra, padchar ); + } + return x; +} + +static void do_printf( int x, int y, char **f ) { + char *fmt = *f; + int *ap; + char buf[ 12 ]; + char ch; + char *str; + int leftadjust; + int width; + int len; + int padchar; + + /* + ** Get characters from the format string and process them + */ + + ap = (int *)( f + 1 ); + + while( (ch = *fmt++) != '\0' ) { + + /* + ** Is it the start of a format code? + */ + + if( ch == '%' ) { + + /* + ** Yes, get the padding and width options (if there). + ** Alignment must come at the beginning, then fill, + ** then width. + */ + + leftadjust = 0; + padchar = ' '; + width = 0; + + ch = *fmt++; + + if( ch == '-' ) { + leftadjust = 1; + ch = *fmt++; + } + + if( ch == '0' ) { + padchar = '0'; + ch = *fmt++; + } + + while( ch >= '0' && ch <= '9' ) { + width *= 10; + width += ch - '0'; + ch = *fmt++; + } + + /* + ** What data type do we have? + */ + switch( ch ) { + + case 'c': + // ch = *( (int *)ap )++; + ch = *ap++; + buf[ 0 ] = ch; + buf[ 1 ] = '\0'; + x = mypadstr( x, y, buf, 1, width, leftadjust, padchar ); + break; + + case 'd': + // len = cvtdec( buf, *( (int *)ap )++ ); + len = cvtdec( buf, *ap++ ); + x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); + break; + + case 's': + // str = *( (char **)ap )++; + str = (char *) (*ap++); + x = mypadstr( x, y, str, -1, width, leftadjust, padchar ); + break; + + case 'x': + // len = cvthex( buf, *( (int *)ap )++ ); + len = cvthex( buf, *ap++ ); + x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); + break; + + case 'o': + // len = cvtoct( buf, *( (int *)ap )++ ); + len = cvtoct( buf, *ap++ ); + x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); + break; + + case 'u': + len = cvtuns( buf, *ap++ ); + x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); + break; + + } + } else { + + /* + ** No - just print it normally. + */ + + if( x != -1 || y != -1 ) { + cio_putchar_at( x, y, ch ); + switch( ch ) { + case '\n': + y += 1; + /* FALL THRU */ + + case '\r': + x = scroll_min_x; + break; + + default: + x += 1; + } + } + else { + cio_putchar( ch ); + } + } + } +} + +void cio_printf_at( unsigned int x, unsigned int y, char *fmt, ... ) { + do_printf( x, y, &fmt ); +} + +void cio_printf( char *fmt, ... ) { + do_printf( -1, -1, &fmt ); +} + +/* +** These are the "standard" IBM AT "Set 1" keycodes. +*/ + +static unsigned char scan_code[ 2 ][ 128 ] = { + { // unshifted characters +/* 00-07 */ '\377', '\033', '1', '2', '3', '4', '5', '6', +/* 08-0f */ '7', '8', '9', '0', '-', '=', '\b', '\t', +/* 10-17 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', +/* 18-1f */ 'o', 'p', '[', ']', '\n', '\377', 'a', 's', +/* 20-27 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', +/* 28-2f */ '\'', '`', '\377', '\\', 'z', 'x', 'c', 'v', +/* 30-37 */ 'b', 'n', 'm', ',', '.', '/', '\377', '*', +/* 38-3f */ '\377', ' ', '\377', '\377', '\377', '\377', '\377', '\377', +/* 40-47 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '7', +/* 48-4f */ '8', '9', '-', '4', '5', '6', '+', '1', +/* 50-57 */ '2', '3', '0', '.', '\377', '\377', '\377', '\377', +/* 58-5f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', +/* 60-67 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', +/* 68-6f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', +/* 70-77 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', +/* 78-7f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377' + }, + + { // shifted characters +/* 00-07 */ '\377', '\033', '!', '@', '#', '$', '%', '^', +/* 08-0f */ '&', '*', '(', ')', '_', '+', '\b', '\t', +/* 10-17 */ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', +/* 18-1f */ 'O', 'P', '{', '}', '\n', '\377', 'A', 'S', +/* 20-27 */ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', +/* 28-2f */ '"', '~', '\377', '|', 'Z', 'X', 'C', 'V', +/* 30-37 */ 'B', 'N', 'M', '<', '>', '?', '\377', '*', +/* 38-3f */ '\377', ' ', '\377', '\377', '\377', '\377', '\377', '\377', +/* 40-47 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '7', +/* 48-4f */ '8', '9', '-', '4', '5', '6', '+', '1', +/* 50-57 */ '2', '3', '0', '.', '\377', '\377', '\377', '\377', +/* 58-5f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', +/* 60-67 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', +/* 68-6f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', +/* 70-77 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', +/* 78-7f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377' + } +}; + +/* +** Scan code masks +*/ + +// 'release' bit +#define REL_BIT 0x80 +#define CODE_BITS 0x7f + +#define IS_PRESS(c) (((c) & REL_BIT) == 0) +#define IS_RELEASE(c) (((c) & REL_BIT) != 0) + +/* +** Scan codes for some special characters +*/ + +// escape code - followed by another code byte +#define SCAN_ESC 0xe0 + +// shift keys: press, release +#define L_SHIFT_DN 0x2a +#define R_SHIFT_DN 0x36 +#define L_SHIFT_UP 0xaa +#define R_SHIFT_UP 0xb6 + +// control keys +#define L_CTRL_DN 0x1d +#define L_CTRL_UP 0x9d + +/* +** I/O communication constants +*/ +#define KBD_DATA 0x60 +#define KBD_STATUS 0x64 +#define READY 0x1 + +/* +** Circular buffer for input characters. Characters are inserted at +** next_space, and are removed at next_char. Buffer is empty if +** these are equal. +*/ +#define C_BUFSIZE 200 + +static char input_buffer[ C_BUFSIZE ]; +static volatile char *next_char = input_buffer; +static volatile char *next_space = input_buffer; + +static volatile char *increment( volatile char *pointer ) { + if( ++pointer >= input_buffer + C_BUFSIZE ) { + pointer = input_buffer; + } + return pointer; +} + +static int input_scan_code( int code ) { + static int shift = 0; + static int ctrl_mask = BMASK8; + int rval = -1; + + /* + ** Do the shift processing + */ + code &= BMASK8; + switch( code ) { + case L_SHIFT_DN: + case R_SHIFT_DN: + shift = 1; + break; + + case L_SHIFT_UP: + case R_SHIFT_UP: + shift = 0; + break; + + case L_CTRL_DN: + ctrl_mask = BMASK5; + break; + + case L_CTRL_UP: + ctrl_mask = BMASK8; + break; + + default: + /* + ** Process ordinary characters only on the press (to handle + ** autorepeat). Ignore undefined scan codes. + */ + if( IS_PRESS(code) ) { + code = scan_code[ shift ][ (int)code ]; + if( code != '\377' ) { + volatile char *next = increment( next_space ); + + /* + ** Store character only if there's room + */ + rval = code & ctrl_mask; + if( next != next_char ) { + *next_space = code & ctrl_mask; + next_space = next; + } + } + } + } + return( rval ); +} + +static void keyboard_isr( int vector, int code ) { + + int data = inb( KBD_DATA ); + int val = input_scan_code( data ); + + // if there is a notification function, call it + if( val != -1 && notify ) + notify( val ); + + outb( PIC1_CMD, PIC_EOI ); +} + +int cio_getchar( void ) { + char c; + int interrupts_enabled = r_eflags() & EFL_IF; + + while( next_char == next_space ) { + if( !interrupts_enabled ) { + /* + ** Must read the next keystroke ourselves. + */ + while( ( inb( KBD_STATUS ) & READY ) == 0 ) { + ; + } + (void) input_scan_code( inb( KBD_DATA ) ); + } + } + + c = *next_char & BMASK8; + next_char = increment( next_char ); + if( c != EOT ) { + cio_putchar( c ); + } + return c; +} + +int cio_gets( char *buffer, unsigned int size ) { + char ch; + int count = 0; + + while( size > 1 ) { + ch = cio_getchar(); + if( ch == EOT ) { + break; + } + *buffer++ = ch; + count += 1; + size -= 1; + if( ch == '\n' ) { + break; + } + } + *buffer = '\0'; + return count; +} + +int cio_input_queue( void ) { + int n_chars = next_space - next_char; + + if( n_chars < 0 ) { + n_chars += C_BUFSIZE; + } + return n_chars; +} + +/* +** Initialization routines +*/ +void cio_init( void (*fcn)(int) ) { + /* + ** Screen dimensions + */ + min_x = SCREEN_MIN_X; + min_y = SCREEN_MIN_Y; + max_x = SCREEN_MAX_X; + max_y = SCREEN_MAX_Y; + + /* + ** Scrolling region + */ + scroll_min_x = SCREEN_MIN_X; + scroll_min_y = SCREEN_MIN_Y; + scroll_max_x = SCREEN_MAX_X; + scroll_max_y = SCREEN_MAX_Y; + + /* + ** Initial cursor location + */ + curr_y = min_y; + curr_x = min_x; + setcursor(); + + /* + ** Notification function (or NULL) + */ + notify = fcn; + + /* + ** Set up the interrupt handler for the keyboard + */ + install_isr( VEC_KBD, keyboard_isr ); +} + +#ifdef SA_DEBUG +int main() { + cio_printf( "%d\n", 123 ); + cio_printf( "%d\n", -123 ); + cio_printf( "%d\n", 0x7fffffff ); + cio_printf( "%d\n", 0x80000001 ); + cio_printf( "%d\n", 0x80000000 ); + cio_printf( "x%14dy\n", 0x80000000 ); + cio_printf( "x%-14dy\n", 0x80000000 ); + cio_printf( "x%014dy\n", 0x80000000 ); + cio_printf( "x%-014dy\n", 0x80000000 ); + cio_printf( "%s\n", "xyz" ); + cio_printf( "|%10s|\n", "xyz" ); + cio_printf( "|%-10s|\n", "xyz" ); + cio_printf( "%c\n", 'x' ); + cio_printf( "|%4c|\n", 'y' ); + cio_printf( "|%-4c|\n", 'y' ); + cio_printf( "|%04c|\n", 'y' ); + cio_printf( "|%-04c|\n", 'y' ); + cio_printf( "|%3d|\n", 5 ); + cio_printf( "|%3d|\n", 54321 ); + cio_printf( "%x\n", 0x123abc ); + cio_printf( "|%04x|\n", 20 ); + cio_printf( "|%012x|\n", 0xfedcba98 ); + cio_printf( "|%-012x|\n", 0x76543210 ); +} + +int curr_x, curr_y, max_x, max_y; +#endif diff --git a/kernel/clock.c b/kernel/clock.c new file mode 100644 index 0000000..96f71c4 --- /dev/null +++ b/kernel/clock.c @@ -0,0 +1,163 @@ +/** +** @file clock.c +** +** @author CSCI-452 class of 20245 +** +** @brief Clock module implementation +*/ + +#define KERNEL_SRC + +#include + +#include +#include + +#include +#include +#include + +/* +** PRIVATE DEFINITIONS +*/ + +/* +** PRIVATE DATA TYPES +*/ + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +// pinwheel control variables +static uint32_t pinwheel; // pinwheel counter +static uint32_t pindex; // index into pinwheel string + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +// current system time +uint32_t system_time; + +/* +** PRIVATE FUNCTIONS +*/ + +/** +** Name: clk_isr +** +** The ISR for the clock +** +** @param vector Vector number for the clock interrupt +** @param code Error code (0 for this interrupt) +*/ +static void clk_isr( int vector, int code ) { + + // spin the pinwheel + + ++pinwheel; + if( pinwheel == (CLOCK_FREQ / 10) ) { + pinwheel = 0; + ++pindex; + cio_putchar_at( 0, 0, "|/-\\"[ pindex & 3 ] ); + } + +#if defined(SYSTEM_STATUS) + // Periodically, dump the queue lengths and the SIO status (along + // with the SIO buffers, if non-empty). + // + // Define the symbol SYSTEM_STATUS with a value equal to the desired + // reporting frequency, in seconds. + + if( (system_time % SEC_TO_TICKS(SYSTEM_STATUS)) == 0 ) { + cio_printf_at( 1, 0, " queues: R[%u] W[%u] S[%u] Z[%u] I[%u] ", + pcb_queue_length(ready), + pcb_queue_length(waiting), + pcb_queue_length(sleeping), + pcb_queue_length(zombie), + pcb_queue_length(sioread) + ); + } +#endif + + // time marches on! + ++system_time; + + // wake up any sleeping processes whose time has come + // + // we give them preference over the current process when + // it is scheduled again + + do { + // if there isn't anyone in the sleep queue, we're done + if( pcb_queue_empty(sleeping) ) { + break; + } + + // peek at the first member of the queue + pcb_t *tmp = pcb_queue_peek( sleeping ); + assert( tmp != NULL ); + + // the sleep queue is sorted in ascending order by wakeup + // time, so we know that the retrieved PCB's wakeup time is + // the earliest of any process on the sleep queue; if that + // time hasn't arrived yet, there's nobody left to awaken + + if( tmp->wakeup > system_time ) { + break; + } + + // OK, we need to wake this process up + assert( pcb_queue_remove(sleeping,&tmp) == SUCCESS ); + schedule( tmp ); + } while( 1 ); + + // next, we decrement the current process' remaining time + current->ticks -= 1; + + // has it expired? + if( current->ticks < 1 ) { + // yes! reschedule it + schedule( current ); + current = NULL; + // and pick a new process + dispatch(); + } + + // tell the PIC we're done + outb( PIC1_CMD, PIC_EOI ); +} + +/* +** PUBLIC FUNCTIONS +*/ + +/** +** Name: clk_init +** +** Initializes the clock module +** +*/ +void clk_init( void ) { + +#if TRACING_INIT + cio_puts( " Clock" ); +#endif + + // start the pinwheel + pinwheel = (CLOCK_FREQ / 10) - 1; + pindex = 0; + + // return to the dawn of time + system_time = 0; + + // configure the clock + uint32_t divisor = PIT_FREQ / CLOCK_FREQ; + outb( PIT_CONTROL_PORT, PIT_0_LOAD | PIT_0_SQUARE ); + outb( PIT_0_PORT, divisor & 0xff ); // LSB of divisor + outb( PIT_0_PORT, (divisor >> 8) & 0xff ); // MSB of divisor + + // register the second-stage ISR + install_isr( VEC_TIMER, clk_isr ); +} diff --git a/kernel/isrs.S b/kernel/isrs.S new file mode 100644 index 0000000..421e6d2 --- /dev/null +++ b/kernel/isrs.S @@ -0,0 +1,374 @@ +/* +** @file isrs.S +** +** @author K. Reek +** @authors Jon Coles, Warren R. Carithers, Margaret Reek +** @author numerous Systems Programming classes +** +** Stubs for ISRs. +** +** This module provides the stubs needed for interrupts to save +** the machine state before calling the ISR. All interrupts have +** their own stub which pushes the interrupt number on the stack. +** This makes it possible for a common ISR to determine which +** interrupted occurred. +*/ + +#define ASM_SRC + + .arch i386 + +#include + +/* +** Configuration options - define in Makefile +** +** TRACE_CX include context restore debugging code +*/ + + .text + +/* +** Macros for the isr stubs. Some interrupts push an error code on +** the stack and others don't; for those that don't we simply push +** a zero so that cleaning up from either type is identical. +** +** Note: these are not marked as global symbols, as they are never +** accessed directly outside of this file. This could be changed +** if need be by adding this line to each macro definition right +** after the #define line: +** +** .global isr_##vector +*/ + +#define ISR(vector) \ +isr_##vector: ; \ + pushl $0 ; \ + pushl $vector ; \ + jmp isr_save + +#define ERR_ISR(vector) \ +isr_##vector: ; \ + pushl $vector ; \ + jmp isr_save + + .globl isr_table + .globl isr_restore + +/* +** This routine saves the machine state, calls the ISR, and then +** restores the machine state and returns from the interrupt. +** +******************************************************************** +******************************************************************** +** NOTE: this code is highly application-specific, and will most ** +** probably require modification to tailor it. ** +** ** +** Examples of mods: switch to/from user stack, context switch ** +** changes, etc. ** +******************************************************************** +******************************************************************** +*/ + +isr_save: + +/* +** Begin by saving the CPU state (except for the FP context information). +** +** At this point, the stack looks like this: +** +** esp -> vector # saved by the entry macro +** error code, or 0 saved by the hardware, or the entry macro +** saved EIP saved by the hardware +** saved CS saved by the hardware +** saved EFLAGS saved by the hardware +*/ + pusha // save E*X, ESP, EBP, ESI, EDI + pushl %ds // save segment registers + pushl %es + pushl %fs + pushl %gs + pushl %ss + +/* +** Stack contents (all 32-bit longwords) and offsets from ESP: +** +** SS GS FS ES DS EDI ESI EBP ESP EBX EDX ECX EAX vec cod EIP CS EFL +** 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 +** +** Note that the saved ESP is the contents before the PUSHA. +** +** Set up parameters for the ISR call. +*/ + movl 52(%esp),%eax // get vector number and error code + movl 56(%esp),%ebx + +/* +*********************** +** MOD FOR 20245 ** +*********************** +*/ + +/* +** We need to switch to the system stack. This requires that we save +** the user context pointer into the current PCB, then load ESP with +** the initial system stack pointer. +*/ + + .globl current + .globl kernel_esp + + // save the context pointer + movl current, %edx + movl %esp, (%edx) + + // also save the page directory pointer + movl %cr3, %ecx + movl %ecx, 4(%edx) + + // switch to the system stack + // + // NOTE: this is inherently non-reentrant! If/when the OS + // is converted from monolithic to something that supports + // reentrant or interruptable ISRs, this code will need to + // be changed to support that! + + movl kernel_esp, %esp + + // we don't change CR3 because all the user PDIRs are + // set up with mappings for the OS in the upper half + +/* +*********************** +** END MOD FOR 20245 ** +*********************** +*/ + + pushl %ebx // put them on the top of the stack ... + pushl %eax // ... as parameters for the ISR + +/* +** Call the ISR +*/ + movl isr_table(,%eax,4),%ebx + call *%ebx + addl $8,%esp // pop the two parameters + +/* +** Context restore begins here +*/ + +isr_restore: + +/* +*********************** +** MOD FOR 20245 ** +*********************** +*/ + movl current, %ebx // return to the user stack + movl (%ebx), %esp // ESP --> context save area + movl 4(%ebx), %ecx // page directory pointer + movl %ecx, %cr3 + + // now we're operating with the user process' + // page directory and stack + +/* +*********************** +** END MOD FOR 20245 ** +*********************** +*/ + +#ifdef TRACE_CX +/* +** DEBUGGING CODE PART 1 +** +** This code will execute during each context restore, and +** should be modified to print out whatever debugging information +** is desired. +** +** By default, it prints out the CPU context being restored; it +** relies on the standard save sequence (see above). +*/ + .globl cio_printf_at + + pushl $fmt + pushl $1 + pushl $0 + call cio_printf_at + addl $12,%esp +/* +** END OF DEBUGGING CODE PART 1 +*/ +#endif + +/* +** Restore the context. +*/ + popl %ss // restore the segment registers + popl %gs + popl %fs + popl %es + popl %ds + popa // restore others + addl $8, %esp // discard the error code and vector + iret // and return + +#ifdef TRACE_CX +/* +** DEBUGGING CODE PART 2 +** +** This format string is arranged according to the ordering of values +** in the context save area on the stack. +*/ +fmt: .ascii " ss=%08x gs=%08x fs=%08x es=%08x ds=%08x\n" + .ascii "edi=%08x esi=%08x ebp=%08x esp=%08x ebx=%08x\n" + .ascii "edx=%08x ecx=%08x eax=%08x vec=%08x cod=%08x\n" + .string "eip=%08x cs=%08x efl=%08x\n" + +/* +** END OF DEBUGGING CODE PART 2 +*/ +#endif + +/* +** Here we generate the individual stubs for each interrupt. +*/ +ISR(0x00); ISR(0x01); ISR(0x02); ISR(0x03); +ISR(0x04); ISR(0x05); ISR(0x06); ISR(0x07); +ERR_ISR(0x08); ISR(0x09); ERR_ISR(0x0a); ERR_ISR(0x0b); +ERR_ISR(0x0c); ERR_ISR(0x0d); ERR_ISR(0x0e); ISR(0x0f); +ISR(0x10); ERR_ISR(0x11); ISR(0x12); ISR(0x13); +ISR(0x14); ERR_ISR(0x15); ISR(0x16); ISR(0x17); +ISR(0x18); ISR(0x19); ISR(0x1a); ISR(0x1b); +ISR(0x1c); ISR(0x1d); ISR(0x1e); ISR(0x1f); +ISR(0x20); ISR(0x21); ISR(0x22); ISR(0x23); +ISR(0x24); ISR(0x25); ISR(0x26); ISR(0x27); +ISR(0x28); ISR(0x29); ISR(0x2a); ISR(0x2b); +ISR(0x2c); ISR(0x2d); ISR(0x2e); ISR(0x2f); +ISR(0x30); ISR(0x31); ISR(0x32); ISR(0x33); +ISR(0x34); ISR(0x35); ISR(0x36); ISR(0x37); +ISR(0x38); ISR(0x39); ISR(0x3a); ISR(0x3b); +ISR(0x3c); ISR(0x3d); ISR(0x3e); ISR(0x3f); +ISR(0x40); ISR(0x41); ISR(0x42); ISR(0x43); +ISR(0x44); ISR(0x45); ISR(0x46); ISR(0x47); +ISR(0x48); ISR(0x49); ISR(0x4a); ISR(0x4b); +ISR(0x4c); ISR(0x4d); ISR(0x4e); ISR(0x4f); +ISR(0x50); ISR(0x51); ISR(0x52); ISR(0x53); +ISR(0x54); ISR(0x55); ISR(0x56); ISR(0x57); +ISR(0x58); ISR(0x59); ISR(0x5a); ISR(0x5b); +ISR(0x5c); ISR(0x5d); ISR(0x5e); ISR(0x5f); +ISR(0x60); ISR(0x61); ISR(0x62); ISR(0x63); +ISR(0x64); ISR(0x65); ISR(0x66); ISR(0x67); +ISR(0x68); ISR(0x69); ISR(0x6a); ISR(0x6b); +ISR(0x6c); ISR(0x6d); ISR(0x6e); ISR(0x6f); +ISR(0x70); ISR(0x71); ISR(0x72); ISR(0x73); +ISR(0x74); ISR(0x75); ISR(0x76); ISR(0x77); +ISR(0x78); ISR(0x79); ISR(0x7a); ISR(0x7b); +ISR(0x7c); ISR(0x7d); ISR(0x7e); ISR(0x7f); +ISR(0x80); ISR(0x81); ISR(0x82); ISR(0x83); +ISR(0x84); ISR(0x85); ISR(0x86); ISR(0x87); +ISR(0x88); ISR(0x89); ISR(0x8a); ISR(0x8b); +ISR(0x8c); ISR(0x8d); ISR(0x8e); ISR(0x8f); +ISR(0x90); ISR(0x91); ISR(0x92); ISR(0x93); +ISR(0x94); ISR(0x95); ISR(0x96); ISR(0x97); +ISR(0x98); ISR(0x99); ISR(0x9a); ISR(0x9b); +ISR(0x9c); ISR(0x9d); ISR(0x9e); ISR(0x9f); +ISR(0xa0); ISR(0xa1); ISR(0xa2); ISR(0xa3); +ISR(0xa4); ISR(0xa5); ISR(0xa6); ISR(0xa7); +ISR(0xa8); ISR(0xa9); ISR(0xaa); ISR(0xab); +ISR(0xac); ISR(0xad); ISR(0xae); ISR(0xaf); +ISR(0xb0); ISR(0xb1); ISR(0xb2); ISR(0xb3); +ISR(0xb4); ISR(0xb5); ISR(0xb6); ISR(0xb7); +ISR(0xb8); ISR(0xb9); ISR(0xba); ISR(0xbb); +ISR(0xbc); ISR(0xbd); ISR(0xbe); ISR(0xbf); +ISR(0xc0); ISR(0xc1); ISR(0xc2); ISR(0xc3); +ISR(0xc4); ISR(0xc5); ISR(0xc6); ISR(0xc7); +ISR(0xc8); ISR(0xc9); ISR(0xca); ISR(0xcb); +ISR(0xcc); ISR(0xcd); ISR(0xce); ISR(0xcf); +ISR(0xd0); ISR(0xd1); ISR(0xd2); ISR(0xd3); +ISR(0xd4); ISR(0xd5); ISR(0xd6); ISR(0xd7); +ISR(0xd8); ISR(0xd9); ISR(0xda); ISR(0xdb); +ISR(0xdc); ISR(0xdd); ISR(0xde); ISR(0xdf); +ISR(0xe0); ISR(0xe1); ISR(0xe2); ISR(0xe3); +ISR(0xe4); ISR(0xe5); ISR(0xe6); ISR(0xe7); +ISR(0xe8); ISR(0xe9); ISR(0xea); ISR(0xeb); +ISR(0xec); ISR(0xed); ISR(0xee); ISR(0xef); +ISR(0xf0); ISR(0xf1); ISR(0xf2); ISR(0xf3); +ISR(0xf4); ISR(0xf5); ISR(0xf6); ISR(0xf7); +ISR(0xf8); ISR(0xf9); ISR(0xfa); ISR(0xfb); +ISR(0xfc); ISR(0xfd); ISR(0xfe); ISR(0xff); + + .data + +/* +** This table contains the addresses where each of the preceding +** stubs begins. This information is needed to initialize the +** Interrupt Descriptor Table in support.c +*/ + .globl isr_stub_table +isr_stub_table: + .long isr_0x00, isr_0x01, isr_0x02, isr_0x03 + .long isr_0x04, isr_0x05, isr_0x06, isr_0x07 + .long isr_0x08, isr_0x09, isr_0x0a, isr_0x0b + .long isr_0x0c, isr_0x0d, isr_0x0e, isr_0x0f + .long isr_0x10, isr_0x11, isr_0x12, isr_0x13 + .long isr_0x14, isr_0x15, isr_0x16, isr_0x17 + .long isr_0x18, isr_0x19, isr_0x1a, isr_0x1b + .long isr_0x1c, isr_0x1d, isr_0x1e, isr_0x1f + .long isr_0x20, isr_0x21, isr_0x22, isr_0x23 + .long isr_0x24, isr_0x25, isr_0x26, isr_0x27 + .long isr_0x28, isr_0x29, isr_0x2a, isr_0x2b + .long isr_0x2c, isr_0x2d, isr_0x2e, isr_0x2f + .long isr_0x30, isr_0x31, isr_0x32, isr_0x33 + .long isr_0x34, isr_0x35, isr_0x36, isr_0x37 + .long isr_0x38, isr_0x39, isr_0x3a, isr_0x3b + .long isr_0x3c, isr_0x3d, isr_0x3e, isr_0x3f + .long isr_0x40, isr_0x41, isr_0x42, isr_0x43 + .long isr_0x44, isr_0x45, isr_0x46, isr_0x47 + .long isr_0x48, isr_0x49, isr_0x4a, isr_0x4b + .long isr_0x4c, isr_0x4d, isr_0x4e, isr_0x4f + .long isr_0x50, isr_0x51, isr_0x52, isr_0x53 + .long isr_0x54, isr_0x55, isr_0x56, isr_0x57 + .long isr_0x58, isr_0x59, isr_0x5a, isr_0x5b + .long isr_0x5c, isr_0x5d, isr_0x5e, isr_0x5f + .long isr_0x60, isr_0x61, isr_0x62, isr_0x63 + .long isr_0x64, isr_0x65, isr_0x66, isr_0x67 + .long isr_0x68, isr_0x69, isr_0x6a, isr_0x6b + .long isr_0x6c, isr_0x6d, isr_0x6e, isr_0x6f + .long isr_0x70, isr_0x71, isr_0x72, isr_0x73 + .long isr_0x74, isr_0x75, isr_0x76, isr_0x77 + .long isr_0x78, isr_0x79, isr_0x7a, isr_0x7b + .long isr_0x7c, isr_0x7d, isr_0x7e, isr_0x7f + .long isr_0x80, isr_0x81, isr_0x82, isr_0x83 + .long isr_0x84, isr_0x85, isr_0x86, isr_0x87 + .long isr_0x88, isr_0x89, isr_0x8a, isr_0x8b + .long isr_0x8c, isr_0x8d, isr_0x8e, isr_0x8f + .long isr_0x90, isr_0x91, isr_0x92, isr_0x93 + .long isr_0x94, isr_0x95, isr_0x96, isr_0x97 + .long isr_0x98, isr_0x99, isr_0x9a, isr_0x9b + .long isr_0x9c, isr_0x9d, isr_0x9e, isr_0x9f + .long isr_0xa0, isr_0xa1, isr_0xa2, isr_0xa3 + .long isr_0xa4, isr_0xa5, isr_0xa6, isr_0xa7 + .long isr_0xa8, isr_0xa9, isr_0xaa, isr_0xab + .long isr_0xac, isr_0xad, isr_0xae, isr_0xaf + .long isr_0xb0, isr_0xb1, isr_0xb2, isr_0xb3 + .long isr_0xb4, isr_0xb5, isr_0xb6, isr_0xb7 + .long isr_0xb8, isr_0xb9, isr_0xba, isr_0xbb + .long isr_0xbc, isr_0xbd, isr_0xbe, isr_0xbf + .long isr_0xc0, isr_0xc1, isr_0xc2, isr_0xc3 + .long isr_0xc4, isr_0xc5, isr_0xc6, isr_0xc7 + .long isr_0xc8, isr_0xc9, isr_0xca, isr_0xcb + .long isr_0xcc, isr_0xcd, isr_0xce, isr_0xcf + .long isr_0xd0, isr_0xd1, isr_0xd2, isr_0xd3 + .long isr_0xd4, isr_0xd5, isr_0xd6, isr_0xd7 + .long isr_0xd8, isr_0xd9, isr_0xda, isr_0xdb + .long isr_0xdc, isr_0xdd, isr_0xde, isr_0xdf + .long isr_0xe0, isr_0xe1, isr_0xe2, isr_0xe3 + .long isr_0xe4, isr_0xe5, isr_0xe6, isr_0xe7 + .long isr_0xe8, isr_0xe9, isr_0xea, isr_0xeb + .long isr_0xec, isr_0xed, isr_0xee, isr_0xef + .long isr_0xf0, isr_0xf1, isr_0xf2, isr_0xf3 + .long isr_0xf4, isr_0xf5, isr_0xf6, isr_0xf7 + .long isr_0xf8, isr_0xf9, isr_0xfa, isr_0xfb + .long isr_0xfc, isr_0xfd, isr_0xfe, isr_0xff diff --git a/kernel/kernel.c b/kernel/kernel.c new file mode 100644 index 0000000..53e50a7 --- /dev/null +++ b/kernel/kernel.c @@ -0,0 +1,381 @@ +/** +** @file kernel.c +** +** @author CSCI-452 class of 20245 +** +** @brief Kernel support routines +*/ + +#define KERNEL_SRC + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** PRIVATE DEFINITIONS +*/ + +/* +** PRIVATE DATA TYPES +*/ + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +// character buffers, usable throughout the OS +// nto guaranteed to retain their contents across an exception return +char b256[256]; // primarily used for message creation +char b512[512]; // used by PANIC macro + +/* +** PRIVATE FUNCTIONS +*/ + +/* +** PRIVATE FUNCTIONS +*/ + +/** +** report - report the system configuration +** +** Prints configuration information about the OS on the console monitor. +** +** @param dtrace Decode the TRACE options +*/ +static void kreport( bool_t dtrace ) { + + cio_puts( "\n-------------------------------\n" ); + cio_printf( "Config: N_PROCS = %d", N_PROCS ); + cio_printf( " N_PRIOS = %d", N_PRIOS ); + cio_printf( " N_STATES = %d", N_STATES ); + cio_printf( " CLOCK = %dHz\n", CLOCK_FREQ ); + + // This code is ugly, but it's the simplest way to + // print out the values of compile-time options + // without spending a lot of execution time at it. + + cio_puts( "Options: " +#ifdef RPT_INT_UNEXP + " R-uint" +#endif +#ifdef RPT_INT_MYSTERY + " R-mint" +#endif +#ifdef TRACE_CX + " CX" +#endif +#ifdef CONSOLE_STATS + " Cstats" +#endif + ); // end of cio_puts() call + +#ifdef SANITY + cio_printf( " SANITY = %d", SANITY ); +#endif +#ifdef STATUS + cio_printf( " STATUS = %d", STATUS ); +#endif + +#if TRACE > 0 + cio_printf( " TRACE = 0x%04x\n", TRACE ); + + // decode the trace settings if that was requested + if( TRACING_SOMETHING && dtrace ) { + + // this one is simpler - we rely on string literal + // concatenation in the C compiler to create one + // long string to print out + + cio_puts( "Tracing:" +#if TRACING_PCB + " PCB" +#endif +#if TRACING_STACK + " STK" +#endif +#if TRACING_QUEUE + " QUE" +#endif +#if TRACING_SCHED + " SCHED" +#endif +#if TRACING_SYSCALLS + " SCALL" +#endif +#if TRACING_SYSRETS + " SRET" +#endif +#if TRACING_EXIT + " EXIT" +#endif +#if TRACING_DISPATCH + " DISPATCH" +#endif +#if TRACING_INIT + " INIT" +#endif +#if TRACING_KMEM + " KM" +#endif +#if TRACING_KMEM_FREELIST + " KMFL" +#endif +#if TRACING_KMEM_INIT + " KMIN" +#endif +#if TRACING_SPAWN + " SPAWN" +#endif +#if TRACING_SIO_STAT + " S_STAT" +#endif +#if TRACING_SIO_ISR + " S_ISR" +#endif +#if TRACING_SIO_RD + " S_RD" +#endif +#if TRACING_SIO_WR + " S_WR" +#endif +#if TRACING_USER + " USER" +#endif +#if TRACING_ELF + " ELF" +#endif + ); // end of cio_puts() call + } +#endif /* TRACE > 0 */ + + cio_puts( "\n-------------------------------\n" ); +} + + +#if defined(CONSOLE_STATS) +/** +** stats - callback routine for console statistics +** +** Called by the CIO module when a key is pressed on the +** console keyboard. Depending on the key, it will print +** statistics on the console display, or will cause the +** user shell process to be dispatched. +** +** This code runs as part of the CIO ISR. +*/ +static void stats( int code ) { + + switch( code ) { + + case 'a': // dump the active table + ptable_dump( "\nActive processes", false ); + break; + + case 'c': // dump context info for all active PCBs + ctx_dump_all( "\nContext dump" ); + break; + + case 'p': // dump the active table and all PCBs + ptable_dump( "\nActive processes", true ); + break; + + case 'q': // dump the queues + // code to dump out any/all queues + pcb_queue_dump( "R", ready ); + pcb_queue_dump( "W", waiting ); + pcb_queue_dump( "S", sleeping ); + pcb_queue_dump( "Z", zombie ); + pcb_queue_dump( "I", sioread ); + break; + + case 'r': // print system configuration information + report( true ); + break; + + // ignore CR and LF + case '\r': // FALL THROUGH + case '\n': + break; + + default: + cio_printf( "console: unknown request '0x%02x'\n", code ); + // FALL THROUGH + + case 'h': // help message + cio_puts( "\nCommands:\n" + " a -- dump the active table\n" + " c -- dump contexts for active processes\n" + " h -- this message\n" + " p -- dump the active table and all PCBs\n" + " q -- dump the queues\n" + " r -- print system configuration\n" + ); + break; + } +} +#endif + +/* +** PUBLIC FUNCTIONS +*/ + +/** +** main - system initialization routine +** +** Called by the startup code immediately before returning into the +** first user process. +** +** Making this type 'int' keeps the compiler happy. +*/ +int main( void ) { + + /* + ** BOILERPLATE CODE - taken from basic framework + ** + ** Initialize interrupt stuff. + */ + + init_interrupts(); // IDT and PIC initialization + + /* + ** Console I/O system. + ** + ** Does not depend on the other kernel modules, so we can + ** initialize it before we initialize the kernel memory + ** and queue modules. + */ + +#if defined(CONSOLE_STATS) + cio_init( stats ); +#else + cio_init( NULL ); // no console callback routine +#endif + + cio_clearscreen(); // wipe out whatever is there + + /* + ** TERM-SPECIFIC CODE STARTS HERE + */ + + /* + ** Initialize various OS modules + ** + ** Other modules (clock, SIO, syscall, etc.) are expected to + ** install their own ISRs in their initialization routines. + */ + + cio_puts( "System initialization starting.\n" ); + cio_puts( "-------------------------------\n" ); + + cio_puts( "Modules:" ); + + // call the module initialization functions, being + // careful to follow any module precedence requirements + + km_init(); // MUST BE FIRST +#if TRACING_KMEM || TRACING_KMEM_FREE + delay( DELAY_2_SEC ); // approximately +#endif + + // other module initialization calls here + clk_init(); // clock + pcb_init(); // process (PCBs, queues, scheduler) +#if TRACING_PCB + delay( DELAY_2_SEC ); +#endif + sio_init(); // serial i/o + sys_init(); // system call +#if TRACING_SYSCALLS || TRACING_SYSRETS + delay( DELAY_2_SEC ); +#endif + vm_init(); // virtual memory + user_init(); // user code handling + + cio_puts( "\nModule initialization complete.\n" ); + cio_puts( "-------------------------------\n" ); + + // report our configuration options + kreport( true ); + + delay( DELAY_3_SEC ); + + /* + ** Other tasks typically performed here: + ** + ** Enabling any I/O devices (e.g., SIO xmit/rcv) + */ + + /* + ** Create the initial user process + ** + ** This code is largely stolen from the fork() and exec() + ** implementations in syscalls.c; if those change, this must + ** also change. + */ + + // if we can't get a PCB, there's no use continuing! + assert( pcb_alloc(&init_pcb) == SUCCESS ); + + // fill in the necessary details + init_pcb->pid = PID_INIT; + init_pcb->state = STATE_NEW; + init_pcb->priority = PRIO_HIGH; + + // find the 'init' program + prog_t *prog = user_locate( Init ); + assert( prog != NULL ); + + // command-line arguments for 'init' + const char *args[2] = { "init", NULL }; + + // load it + assert( user_load(prog,init_pcb,args) == SUCCESS ); + + // send it on its merry way + schedule( init_pcb ); + +#ifdef TRACE_CX + // if we're using a scrolling region, wait a bit more and then set it up + delay( DELAY_7_SEC ); + + // define a scrolling region in the top 7 lines of the screen + cio_setscroll( 0, 7, 99, 99 ); + + // clear it + cio_clearscroll(); + + // clear the top line + cio_puts_at( 0, 0, "* " ); + // separator + cio_puts_at( 0, 6, "================================================================================" ); +#endif + + // switch to the "real" kernel page directory + vm_set_kvm(); + + /* + ** END OF TERM-SPECIFIC CODE + ** + ** Finally, report that we're all done. + */ + + cio_puts( "System initialization complete.\n" ); + cio_puts( "-------------------------------\n" ); + + sio_enable( SIO_RX ); + + return 0; +} diff --git a/kernel/kernel.ld b/kernel/kernel.ld new file mode 100644 index 0000000..2007432 --- /dev/null +++ b/kernel/kernel.ld @@ -0,0 +1,57 @@ +/* +** Simple linker script for the 20245 kernel. +*/ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) + +SECTIONS +{ + /* Link the kernel at this address. */ + /* Must match what is defined in vm.h! */ + . = 0x80010000; + + .text : AT(0x10000) { + *(.text .stub .text.* .gnu.linkonce.t.*) + } + + /* standard symbols */ + PROVIDE(etext = .); + PROVIDE(_etext = .); + + /* put read-only data next */ + .rodata : { + *(.rodata .rodata.* .gnu.linkonce.r.*) + } + + /* Align the data segment at the next page boundary */ + /* . = ALIGN(0x1000); */ + + PROVIDE(data = .); + PROVIDE(_data = .); + + /* The data segment */ + .data : { + *(.data) + } + + PROVIDE(edata = .); + PROVIDE(_edata = .); + + /* page-align the BSS */ + . = ALIGN(0x1000); + + PROVIDE(__bss_start = .); + + .bss : { + *(.bss) + } + + PROVIDE(end = .); + PROVIDE(_end = .); + + /DISCARD/ : { + *(.stab .stab_info .stabstr .eh_frame .note.GNU-stack .note.gnu.property .comment) + } +} diff --git a/kernel/kmem.c b/kernel/kmem.c new file mode 100644 index 0000000..8777f49 --- /dev/null +++ b/kernel/kmem.c @@ -0,0 +1,681 @@ +/** +** @file kmem.c +** +** @author Warren R. Carithers +** @author Kenneth Reek +** @author 4003-506 class of 20013 +** +** @brief Functions to perform dynamic memory allocation in the OS. +** +** NOTE: these should NOT be called by user processes! +** +** This allocator functions as a simple "slab" allocator; it allows +** allocation of either 4096-byte ("page") or 1024-byte ("slice") +** chunks of memory from the free pool. The free pool is initialized +** using the memory map provided by the BIOS during the boot sequence, +** and contains a series of blocks which are each one page of memory +** (4KB, and aligned at 4KB boundaries); they are held in the free list +** in LIFO order, as all pages are created equal. +** +** Each allocator ("page" and "slice") allocates the first block from +** the appropriate free list. On deallocation, the block is added back +** to the free list. +** +** The "slice" allocator operates by taking blocks from the "page" +** allocator and splitting them into four 1K slices, which it then +** manages. Requests are made for slices one at a time. If the free +** list contains an available slice, it is unlinked and returned; +** otherwise, a page is requested from the page allocator, split into +** slices, and the slices are added to the free list, after which the +** first one is returned. The slice free list is a simple linked list +** of these 1K blocks; because they are all the same size, no ordering +** is done on the free list, and no coalescing is performed. +** +** This could be converted into a bitmap-based allocator pretty easily. +** A 4GB address space contains 2^20 (1,048,576) pages; at one bit per +** page frame, that's 131,072 (2^17) bytes to cover all of the address +** space, and that could be reduced by restricting allocatable space +** to a subset of the 4GB space. +** +** Compilation options: +** +** ALLOC_FAIL_PANIC if an internal slice allocation fails, panic +*/ + +#define KERNEL_SRC + +#include + +// all other framework includes are next +#include + +#include + +#include +#include +#include +#include +#include + +/* +** PRIVATE DEFINITIONS +*/ + +// parameters related to word and block sizes + +#define WORD_SIZE sizeof(int) +#define LOG2_OF_WORD_SIZE 2 + +#define LOG2_OF_PAGE_SIZE 12 + +#define LOG2_OF_SLICE_SIZE 10 + +// converters: pages to bytes, bytes to pages + +#define P2B(x) ((x) << LOG2_OF_PAGE_SIZE) +#define B2P(x) ((x) >> LOG2_OF_PAGE_SIZE) + +/* +** Name: adjacent +** +** Arguments: addresses of two blocks +** +** Description: Determines whether the second block immediately +** follows the first one. +*/ +#define adjacent(first,second) \ + ( (void *) (first) + P2B((first)->pages) == (void *) (second) ) + +/* +** PRIVATE DATA TYPES +*/ + +/* +** Memory region information returned by the BIOS +** +** This data consists of a 32-bit integer followed +** by an array of region descriptor structures. +*/ + +// a handy union for playing with 64-bit addresses +typedef union b64_u { + uint32_t part[2]; + uint64_t all; +} b64_t; + +// the halves of a 64-bit address +#define LOW part[0] +#define HIGH part[1] + +// memory region descriptor +typedef struct memregion_s { + b64_t base; // base address + b64_t length; // region length + uint32_t type; // type of region + uint32_t acpi; // ACPI 3.0 info +} __attribute__((__packed__)) region_t; + +/* +** Region types +*/ + +#define REGION_USABLE 1 +#define REGION_RESERVED 2 +#define REGION_ACPI_RECL 3 +#define REGION_ACPI_NVS 4 +#define REGION_BAD 5 + +/* +** ACPI 3.0 bit fields +*/ + +#define REGION_IGNORE 0x01 +#define REGION_NONVOL 0x02 + +/* +** 32-bit and 64-bit address values as 64-bit literals +*/ + +#define ADDR_BIT_32 0x0000000100000000LL +#define ADDR_LOW_HALF 0x00000000ffffffffLL +#define ADDR_HIGH_HALR 0xffffffff00000000LL + +#define ADDR_32_MAX ADDR_LOW_HALF +#define ADDR_64_FIRST ADDR_BIT_32 + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +// freespace pools +static list_t free_pages; +static list_t free_slices; + +// block counts +static uint32_t n_pages; +static uint32_t n_slices; + +// initialization status +static int km_initialized; + +/* +** IMPORTED GLOBAL VARIABLES +*/ + +// this is no longer used; for simple situations, it can be used as +// the KM_LOW_CUTOFF value +// +// extern int _end; // end of the BSS section - provided by the linker + +/* +** FUNCTIONS +*/ + +/* +** FREE LIST MANAGEMENT +*/ + +/** +** Name: add_block +** +** Add a block to the free list. The block will be split into separate +** page-sized fragments which will each be added to the free_pages +** list; each of these will also be modified. +** +** @param[in] base Base address of the block +** @param[in] length Block length, in bytes +*/ +static void add_block( uint32_t base, uint32_t length ) { + + // don't add it if it isn't at least 4K + if( length < SZ_PAGE ) { + return; + } + +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_printf( " add(%08x,%08x): ", base, length ); +#endif + + // verify that the base address is a 4K boundary + if( (base & MOD4K_BITS) != 0 ) { + // nope - how many bytes will we lose from the beginning + uint_t loss = base & MOD4K_BITS; + // adjust the starting address: (n + 4K - 1) / 4K + base = (base + MOD4K_BITS) & MOD4K_MASK; + // adjust the length + length -= loss; + } + + // only want to add multiples of 4K; check the lower bits + if( (length & MOD4K_BITS) != 0 ) { + // round it down to 4K + length &= MOD4K_MASK; + } + + // split the block into pages and add them to the free list + + void *block = (void *) base; + void *blend = (void *) (base + length); + int npages = 0; + +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_printf( "-> base %08x len %08x: ", base, length ); +#endif + + while( block < blend ) { + + // just add to the front of the list + list_add( &free_pages, block ); + ++npages; + + // move to the next block + base += SZ_PAGE; + block = (void *) base; + } + + // add the count to our running total + n_pages += npages; + +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_printf( " -> %d pages\n", npages ); +#endif +} + +/** +** Name: km_init +** +** Find what memory is present on the system and +** construct the list of free memory blocks. +** +** Dependencies: +** Must be called before any other init routine that uses +** dynamic storage is called. +*/ +void km_init( void ) { + int32_t entries; + region_t *region; + +#if TRACING_INIT + // announce that we're starting initialization + cio_puts( " Kmem" ); +#endif + + // initially, nothing in the free lists + free_slices.next = NULL; + free_pages.next = NULL; + n_pages = n_slices = 0; + km_initialized = 0; + + /* + ** We ignore anything below our KM_LOW_CUTOFF address. In theory, + ** we should be able to re-use much of that space; in practice, + ** this is safer. + */ + + // get the list length + entries = *((int32_t *) MMAP_ADDR); + +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_printf( "\nKmem: %d regions\n", entries ); +#endif + + // if there are no entries, we have nothing to do! + if( entries < 1 ) { // note: entries == -1 could occur! + return; + } + + // iterate through the entries, adding things to the freelist + + region = ((region_t *) (MMAP_ADDR + 4)); + + for( int i = 0; i < entries; ++i, ++region ) { + +#if TRACING_KMEM | TRACING_KMEM_INIT + // report this region + cio_printf( "%3d: ", i ); + cio_printf( " B %08x%08x", + region->base.HIGH, region->base.LOW ); + cio_printf( " L %08x%08x", + region->length.HIGH, region->length.LOW ); + cio_printf( " T %08x A %08x", + region->type, region->acpi ); +#endif + + /* + ** Determine whether or not we should ignore this region. + ** + ** We ignore regions for several reasons: + ** + ** ACPI indicates it should be ignored + ** ACPI indicates it's non-volatile memory + ** Region type isn't "usable" + ** Region is above our address limit + ** + ** Currently, only "normal" (type 1) regions are considered + ** "usable" for our purposes. We could potentially expand + ** this to include ACPI "reclaimable" memory. + */ + + // first, check the ACPI one-bit flags + + if( ((region->acpi) & REGION_IGNORE) == 0 ) { +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_puts( " IGN\n" ); +#endif + continue; + } + + if( ((region->acpi) & REGION_NONVOL) != 0 ) { +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_puts( " NVOL\n" ); +#endif + continue; // we'll ignore this, too + } + + // next, the region type + + if( (region->type) != REGION_USABLE ) { +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_puts( " RCLM\n" ); +#endif + continue; // we won't attempt to reclaim ACPI memory (yet) + } + + /* + ** We have a "normal" memory region. We need to verify + ** that it's within our constraints. We won't add anything + ** to the free list if it is: + ** + ** * below our KM_LOW_CUTOFF value + ** * above out KM_HIGH_CUTOFF value. + ** + ** For blocks which straddle one of those limits, we will + ** split it, and only use the portion that's within those + ** bounds. + */ + + // grab the two 64-bit values to simplify things + uint64_t base = region->base.all; + uint64_t length = region->length.all; + uint64_t endpt = base + length; + + // ignore it if it's above our high cutoff point + if( base >= KM_HIGH_CUTOFF || endpt >= KM_HIGH_CUTOFF ) { + + // is the whole thing too high, or just part? + if( base >= KM_HIGH_CUTOFF ) { + // it's all too high! +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_puts( " HIGH\n" ); +#endif + continue; + } + + // some of it is usable - fix the end point + endpt = KM_HIGH_CUTOFF; + } + + // see if it's below our low cutoff point + if( base < KM_LOW_CUTOFF || endpt < KM_LOW_CUTOFF ) { + + // is the whole thing too low, or just part? + if( endpt < KM_LOW_CUTOFF ) { + // it's all below the cutoff! +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_puts( " LOW\n" ); +#endif + continue; + } + + // some of it is usable - reset the base address + base = KM_LOW_CUTOFF; + + // recalculate the length + length = endpt - base; + } + + // we survived the gauntlet - add the new block + // + // we may have changed the base or endpoint, so + // we should recalculate the length + length = endpt - base; + +#if TRACING_KMEM | TRACING_KMEM_INIT + cio_puts( " OK\n" ); +#endif + + uint32_t b32 = base & ADDR_LOW_HALF; + uint32_t l32 = length & ADDR_LOW_HALF; + + add_block( b32, l32 ); + } + + // record the initialization + km_initialized = 1; + +#if TRACING_KMEM | TRACING_KMEM_INIT + delay( DELAY_3_SEC ); +#endif +} + +/** +** Name: km_dump +** +** Dump information about the free lists to the console. By default, +** prints only the list sizes; if 'addrs' is true, also dumps the list +** of page addresses; if 'all' is also true, dumps page addresses and +** slice addresses. +** +** @param addrs Also dump page addresses +** @param both Also dump slice addresses +*/ +void km_dump( bool_t addrs, bool_t both ) { + + // report the sizes + cio_printf( "&free_pages %08x, &free_slices %08x, %u pages, %u slices\n", + (uint32_t) &free_pages, (uint32_t) &free_slices, + n_pages, n_slices ); + + // was that all? + if( !addrs ) { + return; + } + + // dump the addresses of the pages in the free list + uint32_t n = 0; + list_t *block = free_pages.next; + while( block != NULL ) { + if( n && !(n & MOD4_BITS) ) { + // four per line + cio_putchar( '\n' ); + } + cio_printf( " page @ 0x%08x", (uint32_t) block ); + block = block->next; + ++n; + } + + // sanity check - verify that the counts match + if( n != n_pages ) { + sprint( b256, "km_dump: n_pages %u, counted %u!!!\n", + n_pages, n ); + WARNING( b256); + } + + if( !both ) { + return; + } + + // but wait - there's more! + + // also dump the addresses of slices in the slice free list + n = 0; + block = free_slices.next; + while( block != NULL ) { + if( n && !(n & MOD4_BITS) ) { + // four per line + cio_putchar( '\n' ); + } + cio_printf( " slc @ 0x%08x", (uint32_t) block ); + block = block->next; + ++n; + } + + // sanity check - verify that the counts match + if( n != n_slices ) { + sprint( b256, "km_dump: n_slices %u, counted %u!!!\n", + n_slices, n ); + WARNING( b256); + } +} + +/* +** PAGE MANAGEMENT +*/ + +/** +** Name: km_page_alloc +** +** Allocate a page of memory from the free list. +** +** @return a pointer to the beginning of the allocated page, +** or NULL if no memory is available +*/ +void *km_page_alloc( void ) { + + // if km_init() wasn't called first, stop us in our tracks + assert( km_initialized ); + +#if TRACING_KMEM_FREELIST + cio_puts( "KM: pg_alloc()" ); +#endif + + // pointer to the first block + void *page = list_remove( &free_pages ); + + // was a page available? + if( page == NULL ){ + // nope! +#if TRACING_KMEM_FREELIST + cio_puts( " FAIL\n" ); +#endif + return( NULL ); + } + + // fix the count of available pages + --n_pages; + +#if TRACING_KMEM_FREELIST + cio_printf( " -> %08x\n", (uint32_t) page ); +#endif + + return( page ); +} + +/** +** Name: km_page_free +** +** Returns a page to the list of available pages. +** +** @param[in] page Pointer to the page to be returned to the free list +*/ +void km_page_free( void *page ){ + + // verify that km_init() was called first + assert( km_initialized ); + + /* + ** Don't do anything if the address is NULL. + */ + if( page == NULL ){ + return; + } + +#if TRACING_KMEM_FREELIST + cio_printf( "KM: pg_free(%08x)", (uint32_t) page ); +#endif + + /* + ** CRITICAL ASSUMPTION + ** + ** We assume that the block pointer given to us points to a single + ** page-sized block of memory. We make this assumption because we + ** don't track allocation sizes. We can't use the simple "allocate + ** four extra bytes before the returned pointer" scheme to do this + ** because we're managing pages, and the pointers we return must point + ** to page boundaries, so we would wind up allocating an extra page + ** for each allocation. + ** + ** Alternatively, we could keep an array of addresses and block + ** sizes ourselves, but that feels clunky, and would risk running out + ** of table entries if there are lots of allocations (assuming we use + ** a 4KB page to hold the table, at eight bytes per entry we would have + ** 512 entries per page). + ** + ** IF THIS ASSUMPTION CHANGES, THIS CODE MUST BE FIXED!!! + */ + + // link this into the free list + list_add( &free_pages, page ); + + // one more in the pool + ++n_pages; +} + +/* +** SLICE MANAGEMENT +*/ + +/* +** Slices are 1024-byte fragments from pages. We maintain a free list of +** slices for those parts of the OS which don't need full 4096-byte chunks +** of space. +*/ + +/** +** Name: carve_slices +** +** Split an allocated page into four slices and add +** them to the "free slices" list. +** +** @param page Pointer to the page to be carved up +*/ +static void carve_slices( void *page ) { + + // sanity check + assert1( page != NULL ); + + // create the four slices from it + uint8_t *ptr = (uint8_t *) page; + for( int i = 0; i < 4; ++i ) { + km_slice_free( (void *) ptr ); + ptr += SZ_SLICE; + ++n_slices; + } +} + +/** +** Name: km_slice_alloc +** +** Dynamically allocates a slice (1/4 of a page). If no +** memory is available, we return NULL (unless ALLOC_FAIL_PANIC +** was defined, in which case we panic). +** +** @return a pointer to the allocated slice +*/ +void *km_slice_alloc( void ) { + + // verify that km_init() was called first + assert( km_initialized ); + +#if TRACING_KMEM_FREELIST + cio_printf( "KM: sl_alloc()\n" ); +#endif + + // if we are out of slices, create a few more + if( free_slices.next == NULL ) { + void *new = km_page_alloc(); + if( new == NULL ) { + // can't get any more space +#if ALLOC_FAIL_PANIC + PANIC( 0, "slice new alloc failed" ); +#else + return NULL; +#endif + } + carve_slices( new ); + } + + // take the first one from the free list + void *slice = list_remove( &free_slices ); + assert( slice != NULL ); + --n_slices; + + // make it nice and shiny for the caller + memclr( (void *) slice, SZ_SLICE ); + + return( slice ); +} + +/** +** Name: km_slice_free +** +** Returns a slice to the list of available slices. +** +** We make no attempt to merge slices, as we treat them as +** independent blocks of memory (like pages). +** +** @param[in] block Pointer to the slice (1/4 page) to be freed +*/ +void km_slice_free( void *block ) { + + // verify that km_init() was called first + assert( km_initialized ); + +#if TRACING_KMEM_FREELIST + cio_printf( "KM: sl_free(%08x)\n", (uint32_t) block ); +#endif + + // just add it to the front of the free list + list_add( &free_slices, block ); + --n_slices; +} diff --git a/kernel/list.c b/kernel/list.c new file mode 100644 index 0000000..084000a --- /dev/null +++ b/kernel/list.c @@ -0,0 +1,64 @@ +/** +** @file list.c +** +** @author Warren R. Carithers +** +** @brief Support for a basic linked list data type. +** +** This module provides a very basic linked list data structure. +** A list can contain anything that has a pointer field in the first +** four bytes; these routines assume those bytes contain a pointer to +** the following entry in the list, whatever that may be. +*/ + +#define KERNEL_SRC + +#include + +#include + +/* +** FUNCTIONS +*/ + +/** +** Name: list_add +** +** Add the supplied data to the beginning of the specified list. +** +** @param[in,out] list The address of a list_t variable +** @param[in] data The data to prepend to the list +*/ +void list_add( list_t *list, void *data ) { + + // sanity checks + assert1( list != NULL ); + assert1( data != NULL ); + + list_t *tmp = (list_t *)data; + tmp->next = list->next; + list->next = tmp; +} + +/** +** Name: list_remove +** +** Remove the first entry from a linked list. +** +** @param[in,out] list The address of a list_t variable +** +** @return a pointer to the removed data, or NULL if the list was empty +*/ +void *list_remove( list_t *list ) { + + assert1( list != NULL ); + + list_t *data = list->next; + if( data != NULL ) { + list->next = data->next; + data->next = NULL; + } + + return (void *)data; +} + diff --git a/kernel/procs.c b/kernel/procs.c new file mode 100644 index 0000000..96bb3fd --- /dev/null +++ b/kernel/procs.c @@ -0,0 +1,1136 @@ +/* +** @file procs.c +** +** @author CSCI-452 class of 20245 +** +** @brief Process-related implementations +*/ + +#define KERNEL_SRC + +#include + +#include +#include + +/* +** PRIVATE DEFINITIONS +*/ + +// determine if a queue is empty; assumes 'q' is a valid pointer +#define PCB_QUEUE_EMPTY(q) ((q)->head == NULL) + +/* +** PRIVATE DATA TYPES +*/ + +/* +** PCB Queue structure +** +** Opaque to the rest of the kernel +** +** Typedef'd in the header: typedef struct pcb_queue_s *pcb_queue_t; +*/ +struct pcb_queue_s { + pcb_t *head; + pcb_t *tail; + enum pcb_queue_order_e order; +}; + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +// collection of queues +static struct pcb_queue_s pcb_freelist_queue; +static struct pcb_queue_s ready_queue; +static struct pcb_queue_s waiting_queue; +static struct pcb_queue_s sleeping_queue; +static struct pcb_queue_s zombie_queue; +static struct pcb_queue_s sioread_queue; + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +// public-facing queue handles +pcb_queue_t pcb_freelist; +pcb_queue_t ready; +pcb_queue_t waiting; +pcb_queue_t sleeping; +pcb_queue_t zombie; +pcb_queue_t sioread; + +// pointer to the currently-running process +pcb_t *current; + +// the process table +pcb_t ptable[N_PROCS]; + +// next available PID +uint_t next_pid; + +// pointer to the PCB for the 'init' process +pcb_t *init_pcb; + +// table of state name strings +const char *state_str[N_STATES] = { + [ STATE_UNUSED ] = "Unu", // "Unused" + [ STATE_NEW ] = "New", + [ STATE_READY ] = "Rdy", // "Ready" + [ STATE_RUNNING ] = "Run", // "Running" + [ STATE_SLEEPING ] = "Slp", // "Sleeping" + [ STATE_BLOCKED ] = "Blk", // "Blocked" + [ STATE_WAITING ] = "Wat", // "Waiting" + [ STATE_KILLED ] = "Kil", // "Killed" + [ STATE_ZOMBIE ] = "Zom" // "Zombie" +}; + +// table of priority name strings +const char *prio_str[N_PRIOS] = { + [ PRIO_HIGH ] = "High", + [ PRIO_STD ] = "User", + [ PRIO_LOW ] = "Low ", + [ PRIO_DEFERRED ] = "Def " +}; + +// table of queue ordering name strings +const char *ord_str[N_PRIOS] = { + [ O_FIFO ] = "FIFO", + [ O_PRIO ] = "PRIO", + [ O_PID ] = "PID ", + [ O_WAKEUP ] = "WAKE" +}; + +/* +** PRIVATE FUNCTIONS +*/ + +/** +** Priority search functions. These are used to traverse a supplied +** queue looking for the queue entry that would precede the supplied +** PCB when that PCB is inserted into the queue. +** +** Variations: +** find_prev_wakeup() compares wakeup times +** find_prev_priority() compares process priorities +** find_prev_pid() compares PIDs +** +** Each assumes the queue should be in ascending order by the specified +** comparison value. +** +** @param[in] queue The queue to search +** @param[in] pcb The PCB to look for +** +** @return a pointer to the predecessor in the queue, or NULL if +** this PCB would be at the beginning of the queue. +*/ +static pcb_t *find_prev_wakeup( pcb_queue_t queue, pcb_t *pcb ) { + + // sanity checks! + assert1( queue != NULL ); + assert1( pcb != NULL ); + + pcb_t *prev = NULL; + pcb_t *curr = queue->head; + + while( curr != NULL && curr->wakeup <= pcb->wakeup ) { + prev = curr; + curr = curr->next; + } + + return prev; +} + +static pcb_t *find_prev_priority( pcb_queue_t queue, pcb_t *pcb ) { + + // sanity checks! + assert1( queue != NULL ); + assert1( pcb != NULL ); + + pcb_t *prev = NULL; + pcb_t *curr = queue->head; + + while( curr != NULL && curr->priority <= pcb->priority ) { + prev = curr; + curr = curr->next; + } + + return prev; +} + +static pcb_t *find_prev_pid( pcb_queue_t queue, pcb_t *pcb ) { + + // sanity checks! + assert1( queue != NULL ); + assert1( pcb != NULL ); + + pcb_t *prev = NULL; + pcb_t *curr = queue->head; + + while( curr != NULL && curr->pid <= pcb->pid ) { + prev = curr; + curr = curr->next; + } + + return prev; +} + +/* +** PUBLIC FUNCTIONS +*/ + +// a macro to simplify queue setup +#define QINIT(q,s) \ + q = &q##_queue; \ + if( pcb_queue_reset(q,s) != SUCCESS ) { \ + PANIC( 0, "pcb_init can't reset " # q ); \ + } + +/** +** Name: pcb_init +** +** Initialization for the Process module. +*/ +void pcb_init( void ) { + +#if TRACING_INIT + cio_puts( " Procs" ); +#endif + + // there is no current process + current = NULL; + + // set up the external links to the queues + QINIT( pcb_freelist, O_FIFO ); + QINIT( ready, O_PRIO ); + QINIT( waiting, O_PID ); + QINIT( sleeping, O_WAKEUP ); + QINIT( zombie, O_PID ); + QINIT( sioread, O_FIFO ); + + /* + ** We statically allocate our PCBs, so we need to add them + ** to the freelist before we can use them. If this changes + ** so that we dynamicallyl allocate PCBs, this step either + ** won't be required, or could be used to pre-allocate some + ** number of PCB structures for future use. + */ + + pcb_t *ptr = ptable; + for( int i = 0; i < N_PROCS; ++i ) { + pcb_free( ptr ); + ++ptr; + } +} + +/** +** Name: pcb_alloc +** +** Allocate a PCB from the list of free PCBs. +** +** @param pcb Pointer to a pcb_t * where the PCB pointer will be returned. +** +** @return status of the allocation attempt +*/ +int pcb_alloc( pcb_t **pcb ) { + + // sanity check! + assert1( pcb != NULL ); + + // remove the first PCB from the free list + pcb_t *tmp; + if( pcb_queue_remove(pcb_freelist,&tmp) != SUCCESS ) { + return E_NO_PCBS; + } + + *pcb = tmp; + return SUCCESS; +} + +/** +** Name: pcb_free +** +** Return a PCB to the list of free PCBs. +** +** @param pcb Pointer to the PCB to be deallocated. +*/ +void pcb_free( pcb_t *pcb ) { + + if( pcb != NULL ) { + // mark the PCB as available + pcb->state = STATE_UNUSED; + + // add it to the free list + int status = pcb_queue_insert( pcb_freelist, pcb ); + + // if that failed, we're in trouble + if( status != SUCCESS ) { + sprint( b256, "pcb_free(0x%08x) status %d", (uint32_t) pcb, + status ); + PANIC( 0, b256 ); + } + } +} + +/** +** Name: pcb_zombify +** +** Turn the indicated process into a Zombie. This function +** does most of the real work for exit() and kill() calls. +** Is also called from the scheduler and dispatcher. +** +** @param pcb Pointer to the newly-undead PCB +*/ +void pcb_zombify( register pcb_t *victim ) { + + // should this be an error? + if( victim == NULL ) { + return; + } + + // every process must have a parent, even if it's 'init' + assert( victim->parent != NULL ); + + /* + ** We need to locate the parent of this process. We also need + ** to reparent any children of this process. We do these in + ** a single loop. + */ + pcb_t *parent = victim->parent; + pcb_t *zchild = NULL; + + // two PIDs we will look for + uint_t vicpid = victim->pid; + + // speed up access to the process table entries + register pcb_t *curr = ptable; + + for( int i = 0; i < N_PROCS; ++i, ++curr ) { + + // make sure this is a valid entry + if( curr->state == STATE_UNUSED ) { + continue; + } + + // if this is our parent, just keep going - we continue + // iterating to find all the children of this process. + if( curr == parent ) { + continue; + } + + if( curr->parent == victim ) { + + // found a child - reparent it + curr->parent = init_pcb; + + // see if this child is already undead + if( curr->state == STATE_ZOMBIE ) { + // if it's already a zombie, remember it, so we + // can pass it on to 'init'; also, if there are + // two or more zombie children, it doesn't matter + // which one we pick here, as the others will be + // collected when 'init' loops + zchild = curr; + } + + } + } + + /* + ** If we found a child that was already terminated, we need to + ** wake up the init process if it's already waiting. + ** + ** Note: we only need to do this for one Zombie child process - + ** init will loop and collect the others after it finishes with + ** this one. + ** + ** Also note: it's possible that the exiting process' parent is + ** also init, which means we're letting one of zombie children + ** of the exiting process be cleaned up by init before the + ** existing process itself is cleaned up by init. This will work, + ** because after init cleans up the zombie, it will loop and + ** call waitpid() again, by which time this exiting process will + ** be marked as a zombie. + */ + if( zchild != NULL && init_pcb->state == STATE_WAITING ) { + + // dequeue the zombie + assert( pcb_queue_remove_this(zombie,zchild) == SUCCESS ); + + assert( pcb_queue_remove_this(waiting,init_pcb) == SUCCESS ); + + // intrinsic return value is the PID + RET(init_pcb) = zchild->pid; + + // may also want to return the exit status + int32_t *ptr = (int32_t *) ARG(init_pcb,2); + + if( ptr != NULL ) { + // ******************************************************** + // ** Potential VM issue here! This code assigns the exit + // ** status into a variable in the parent's address space. + // ** This works in the baseline because we aren't using + // ** any type of memory protection. If address space + // ** separation is implemented, this code will very likely + // ** STOP WORKING, and will need to be fixed. + // ******************************************************** + *ptr = zchild->exit_status; + } + + // all done - schedule 'init', and clean up the zombie + schedule( init_pcb ); + pcb_cleanup( zchild ); + } + + /* + ** Now, deal with the parent of this process. If the parent is + ** already waiting, just wake it up and clean up this process. + ** Otherwise, this process becomes a zombie. + ** + ** Note: if the exiting process' parent is init and we just woke + ** init up to deal with a zombie child of the exiting process, + ** init's status won't be Waiting any more, so we don't have to + ** worry about it being scheduled twice. + */ + + if( parent->state == STATE_WAITING ) { + + // verify that the parent is either waiting for this process + // or is waiting for any of its children + uint32_t target = ARG(parent,1); + + if( target == 0 || target == vicpid ) { + + // the parent is waiting for this child or is waiting + // for any of its children, so we can wake it up. + + // intrinsic return value is the PID + RET(parent) = vicpid; + + // may also want to return the exit status + int32_t *ptr = (int32_t *) ARG(parent,2); + + if( ptr != NULL ) { + // ******************************************************** + // ** Potential VM issue here! This code assigns the exit + // ** status into a variable in the parent's address space. + // ** This works in the baseline because we aren't using + // ** any type of memory protection. If address space + // ** separation is implemented, this code will very likely + // ** STOP WORKING, and will need to be fixed. + // ******************************************************** + *ptr = victim->exit_status; + } + + // all done - schedule the parent, and clean up the zombie + schedule( parent ); + pcb_cleanup( victim ); + + return; + } + } + + /* + ** The parent isn't waiting OR is waiting for a specific child + ** that isn't this exiting process, so we become a Zombie. + ** + ** This code assumes that Zombie processes are *not* in + ** a queue, but instead are just in the process table with + ** a state of 'Zombie'. This simplifies life immensely, + ** because we won't need to dequeue it when it is collected + ** by its parent. + */ + + victim->state = STATE_ZOMBIE; + assert( pcb_queue_insert(zombie,victim) == SUCCESS ); + + /* + ** Note: we don't call _dispatch() here - we leave that for + ** the calling routine, as it's possible we don't need to + ** choose a new current process. + */ +} + +/** +** Name: pcb_cleanup +** +** Reclaim a process' data structures +** +** @param pcb The PCB to reclaim +*/ +void pcb_cleanup( pcb_t *pcb ) { + +#if TRACING_PCB + cio_printf( "** pcb_cleanup(0x%08x)\n", (uint32_t) pcb ); +#endif + + // avoid deallocating a NULL pointer + if( pcb == NULL ) { + // should this be an error? + return; + } + + // we need to release all the VM data structures and frames + user_cleanup( pcb ); + + // release the PCB itself + pcb_free( pcb ); +} + +/** +** Name: pcb_find_pid +** +** Locate the PCB for the process with the specified PID +** +** @param pid The PID to be located +** +** @return Pointer to the PCB, or NULL +*/ +pcb_t *pcb_find_pid( uint_t pid ) { + + // must be a valid PID + if( pid < 1 ) { + return NULL; + } + + // scan the process table + pcb_t *p = ptable; + + for( int i = 0; i < N_PROCS; ++i, ++p ) { + if( p->pid == pid && p->state != STATE_UNUSED ) { + return p; + } + } + + // didn't find it! + return NULL; +} + +/** +** Name: pcb_find_ppid +** +** Locate the PCB for the process with the specified parent +** +** @param pid The PID to be located +** +** @return Pointer to the PCB, or NULL +*/ +pcb_t *pcb_find_ppid( uint_t pid ) { + + // must be a valid PID + if( pid < 1 ) { + return NULL; + } + + // scan the process table + pcb_t *p = ptable; + + for( int i = 0; i < N_PROCS; ++i, ++p ) { + assert1( p->parent != NULL ); + if( p->parent->pid == pid && p->parent->state != STATE_UNUSED ) { + return p; + } + } + + // didn't find it! + return NULL; +} + +/** +** Name: pcb_queue_reset +** +** Initialize a PCB queue. We assume that whatever data may be +** in the queue structure can be overwritten. +** +** @param queue[out] The queue to be initialized +** @param order[in] The desired ordering for the queue +** +** @return status of the init request +*/ +int pcb_queue_reset( pcb_queue_t queue, enum pcb_queue_order_e style ) { + + // sanity check + assert1( queue != NULL ); + + // make sure the style is valid + if( style < O_FIRST_STYLE || style > O_LAST_STYLE ) { + return E_BAD_PARAM; + } + + // reset the queue + queue->head = queue->tail = NULL; + queue->order = style; + + return SUCCESS; +} + +/** +** Name: pcb_queue_empty +** +** Determine whether a queue is empty. Essentially just a wrapper +** for the PCB_QUEUE_EMPTY() macro, for use outside this module. +** +** @param[in] queue The queue to check +** +** @return true if the queue is empty, else false +*/ +bool_t pcb_queue_empty( pcb_queue_t queue ) { + + // if there is no queue, blow up + assert1( queue != NULL ); + + return PCB_QUEUE_EMPTY(queue); +} + +/** +** Name: pcb_queue_length +** +** Return the count of elements in the specified queue. +** +** @param[in] queue The queue to check +** +** @return the count (0 if the queue is empty) +*/ +uint_t pcb_queue_length( const pcb_queue_t queue ) { + + // sanity check + assert1( queue != NULL ); + + // this is pretty simple + register pcb_t *tmp = queue->head; + register int num = 0; + + while( tmp != NULL ) { + ++num; + tmp = tmp->next; + } + + return num; +} + +/** +** Name: pcb_queue_insert +** +** Inserts a PCB into the indicated queue. +** +** @param queue[in,out] The queue to be used +** @param pcb[in] The PCB to be inserted +** +** @return status of the insertion request +*/ +int pcb_queue_insert( pcb_queue_t queue, pcb_t *pcb ) { + + // sanity checks + assert1( queue != NULL ); + assert1( pcb != NULL ); + + // if this PCB is already in a queue, we won't touch it + if( pcb->next != NULL ) { + // what to do? we let the caller decide + return E_BAD_PARAM; + } + + // is the queue empty? + if( queue->head == NULL ) { + queue->head = queue->tail = pcb; + return SUCCESS; + } + assert1( queue->tail != NULL ); + + // no, so we need to search it + pcb_t *prev = NULL; + + // find the predecessor node + switch( queue->order ) { + case O_FIFO: + prev = queue->tail; + break; + case O_PRIO: + prev = find_prev_priority(queue,pcb); + break; + case O_PID: + prev = find_prev_pid(queue,pcb); + break; + case O_WAKEUP: + prev = find_prev_wakeup(queue,pcb); + break; + default: + // do we need something more specific here? + return E_BAD_PARAM; + } + + // OK, we found the predecessor node; time to do the insertion + + if( prev == NULL ) { + + // there is no predecessor, so we're + // inserting at the front of the queue + pcb->next = queue->head; + if( queue->head == NULL ) { + // empty queue!?! - should we panic? + queue->tail = pcb; + } + queue->head = pcb; + + } else if( prev->next == NULL ) { + + // append at end + prev->next = pcb; + queue->tail = pcb; + + } else { + + // insert between prev & prev->next + pcb->next = prev->next; + prev->next = pcb; + + } + + return SUCCESS; +} + +/** +** Name: pcb_queue_remove +** +** Remove the first PCB from the indicated queue. +** +** @param queue[in,out] The queue to be used +** @param pcb[out] Pointer to where the PCB pointer will be saved +** +** @return status of the removal request +*/ +int pcb_queue_remove( pcb_queue_t queue, pcb_t **pcb ) { + + //sanity checks + assert1( queue != NULL ); + assert1( pcb != NULL ); + + // can't get anything if there's nothing to get! + if( PCB_QUEUE_EMPTY(queue) ) { + return E_EMPTY_QUEUE; + } + + // take the first entry from the queue + pcb_t *tmp = queue->head; + queue->head = tmp->next; + + // disconnect it completely + tmp->next = NULL; + + // was this the last thing in the queue? + if( queue->head == NULL ) { + // yes, so clear the tail pointer for consistency + queue->tail = NULL; + } + + // save the pointer + *pcb = tmp; + + return SUCCESS; +} + +/** +** Name: pcb_queue_remove_this +** +** Remove the specified PCB from the indicated queue. +** +** We don't return the removed pointer, because the calling +** routine must already have it (because it was supplied +** to us in the call). +** +** @param queue[in,out] The queue to be used +** @param pcb[in] Pointer to the PCB to be removed +** +** @return status of the removal request +*/ +int pcb_queue_remove_this( pcb_queue_t queue, pcb_t *pcb ) { + + //sanity checks + assert1( queue != NULL ); + assert1( pcb != NULL ); + + // can't get anything if there's nothing to get! + if( PCB_QUEUE_EMPTY(queue) ) { + return E_EMPTY_QUEUE; + } + + // iterate through the queue until we find the desired PCB + pcb_t *prev = NULL; + pcb_t *curr = queue->head; + + while( curr != NULL && curr != pcb ) { + prev = curr; + curr = curr->next; + } + + // case prev curr next interpretation + // ==== ==== ==== ==== ============================ + // 1. 0 0 -- *** CANNOT HAPPEN *** + // 2. 0 !0 0 removing only element + // 3. 0 !0 !0 removing first element + // 4. !0 0 -- *** NOT FOUND *** + // 5. !0 !0 0 removing from end + // 6. !0 !0 !0 removing from middle + + if( curr == NULL ) { + // case 1 + assert( prev != NULL ); + // case 4 + return E_NOT_FOUND; + } + + // connect predecessor to successor + if( prev != NULL ) { + // not the first element + // cases 5 and 6 + prev->next = curr->next; + } else { + // removing first element + // cases 2 and 3 + queue->head = curr->next; + } + + // if this was the last node (cases 2 and 5), + // also need to reset the tail pointer + if( curr->next == NULL ) { + // if this was the only entry (2), prev is NULL, + // so this works for that case, too + queue->tail = prev; + } + + // unlink current from queue + curr->next = NULL; + + // there's a possible consistancy problem here if somehow + // one of the queue pointers is NULL and the other one + // is not NULL + + assert1( + (queue->head == NULL && queue->tail == NULL) || + (queue->head != NULL && queue->tail != NULL) + ); + + return SUCCESS; +} + +/** +** Name: pcb_queue_peek +** +** Return the first PCB from the indicated queue, but don't +** remove it from the queue. +** +** @param queue[in] The queue to be used +** +** @return the PCB poiner, or NULL if the queue is empty +*/ +pcb_t *pcb_queue_peek( const pcb_queue_t queue ) { + + //sanity check + assert1( queue != NULL ); + + // can't get anything if there's nothing to get! + if( PCB_QUEUE_EMPTY(queue) ) { + return NULL; + } + + // just return the first entry from the queue + return queue->head; +} + +/* +** Scheduler routines +*/ + +/** +** schedule(pcb) +** +** Schedule the supplied process +** +** @param pcb Pointer to the PCB of the process to be scheduled +*/ +void schedule( pcb_t *pcb ) { + + // sanity check + assert1( pcb != NULL ); + + // check for a killed process + if( pcb->state == STATE_KILLED ) { + // TODO figure out what to do now + return; + } + + // mark it as ready + pcb->state = STATE_READY; + + // add it to the ready queue + if( pcb_queue_insert(ready,pcb) != SUCCESS ) { + PANIC( 0, "schedule insert fail" ); + } +} + +/** +** dispatch() +** +** Select the next process to receive the CPU +*/ +void dispatch( void ) { + + // verify that there is no current process + assert( current == NULL ); + + // grab whoever is at the head of the queue + int status = pcb_queue_remove( ready, ¤t ); + if( status != SUCCESS ) { + sprint( b256, "dispatch queue remove failed, code %d", status ); + PANIC( 0, b256 ); + } + + // set the process up for success + current->state = STATE_RUNNING; + current->ticks = QUANTUM_STANDARD; +} + + +/* +** Debugging/tracing routines +*/ + +/** +** ctx_dump(msg,context) +** +** Dumps the contents of this process context to the console +** +** @param msg[in] An optional message to print before the dump +** @param c[in] The context to dump out +*/ +void ctx_dump( const char *msg, register context_t *c ) { + + // first, the message (if there is one) + if( msg ) { + cio_puts( msg ); + } + + // the pointer + cio_printf( " @ %08x: ", (uint32_t) c ); + + // if it's NULL, why did you bother calling me? + if( c == NULL ) { + cio_puts( " NULL???\n" ); + return; + } + + // now, the contents + cio_printf( "ss %04x gs %04x fs %04x es %04x ds %04x cs %04x\n", + c->ss & 0xff, c->gs & 0xff, c->fs & 0xff, + c->es & 0xff, c->ds & 0xff, c->cs & 0xff ); + cio_printf( " edi %08x esi %08x ebp %08x esp %08x\n", + c->edi, c->esi, c->ebp, c->esp ); + cio_printf( " ebx %08x edx %08x ecx %08x eax %08x\n", + c->ebx, c->edx, c->ecx, c->eax ); + cio_printf( " vec %08x cod %08x eip %08x eflags %08x\n", + c->vector, c->code, c->eip, c->eflags ); +} + +/** +** ctx_dump_all(msg) +** +** dump the process context for all active processes +** +** @param msg[in] Optional message to print +*/ +void ctx_dump_all( const char *msg ) { + + if( msg != NULL ) { + cio_puts( msg ); + } + + int n = 0; + register pcb_t *pcb = ptable; + for( int i = 0; i < N_PROCS; ++i, ++pcb ) { + if( pcb->state != STATE_UNUSED ) { + ++n; + cio_printf( "%2d(%d): ", n, pcb->pid ); + ctx_dump( NULL, pcb->context ); + } + } +} + +/** +** _pcb_dump(msg,pcb) +** +** Dumps the contents of this PCB to the console +** +** @param msg[in] An optional message to print before the dump +** @param pcb[in] The PCB to dump +** @param all[in] Dump all the contents? +*/ +void pcb_dump( const char *msg, register pcb_t *pcb, bool_t all ) { + + // first, the message (if there is one) + if( msg ) { + cio_puts( msg ); + } + + // the pointer + cio_printf( " @ %08x:", (uint32_t) pcb ); + + // if it's NULL, why did you bother calling me? + if( pcb == NULL ) { + cio_puts( " NULL???\n" ); + return; + } + + cio_printf( " %d", pcb->pid ); + cio_printf( " %s", + pcb->state >= N_STATES ? "???" : state_str[pcb->state] ); + + if( !all ) { + // just printing IDs and states on one line + return; + } + + // now, the rest of the contents + cio_printf( " %s", + pcb->priority >= N_PRIOS ? "???" : prio_str[pcb->priority] ); + + cio_printf( " ticks %u xit %d wake %08x\n", + pcb->ticks, pcb->exit_status, pcb->wakeup ); + + cio_printf( " parent %08x", (uint32_t)pcb->parent ); + if( pcb->parent != NULL ) { + cio_printf( " (%u)", pcb->parent->pid ); + } + + cio_printf( " next %08x context %08x pde %08x", (uint32_t) pcb->next, + (uint32_t) pcb->context, (uint32_t) pcb->pdir ); + + cio_putchar( '\n' ); +} + +/** +** pcb_queue_dump(msg,queue,contents) +** +** Dump the contents of the specified queue to the console +** +** @param msg[in] Optional message to print +** @param queue[in] The queue to dump +** @param contents[in] Also dump (some) contents? +*/ +void pcb_queue_dump( const char *msg, pcb_queue_t queue, bool_t contents ) { + + // report on this queue + cio_printf( "%s: ", msg ); + if( queue == NULL ) { + cio_puts( "NULL???\n" ); + return; + } + + // first, the basic data + cio_printf( "head %08x tail %08x", + (uint32_t) queue->head, (uint32_t) queue->tail ); + + // next, how the queue is ordered + cio_printf( " order %s\n", + queue->order >= N_ORDERINGS ? "????" : ord_str[queue->order] ); + + // if there are members in the queue, dump the first few PIDs + if( contents && queue->head != NULL ) { + cio_puts( " PIDs: " ); + pcb_t *tmp = queue->head; + for( int i = 0; i < 5 && tmp != NULL; ++i, tmp = tmp->next ) { + cio_printf( " [%u]", tmp->pid ); + } + + if( tmp != NULL ) { + cio_puts( " ..." ); + } + + cio_putchar( '\n' ); + } +} + +/** +** ptable_dump(msg,all) +** +** dump the contents of the "active processes" table +** +** @param msg[in] Optional message to print +** @param all[in] Dump all or only part of the relevant data +*/ +void ptable_dump( const char *msg, bool_t all ) { + + if( msg ) { + cio_puts( msg ); + } + cio_putchar( ' ' ); + + int used = 0; + int empty = 0; + + register pcb_t *pcb = ptable; + for( int i = 0; i < N_PROCS; ++i ) { + if( pcb->state == STATE_UNUSED ) { + + // an empty slot + ++empty; + + } else { + + // a non-empty slot + ++used; + + // if not dumping everything, add commas if needed + if( !all && used ) { + cio_putchar( ',' ); + } + + // report the table slot # + cio_printf( " #%d:", i ); + + // and dump the contents + pcb_dump( NULL, pcb, all ); + } + } + + // only need this if we're doing one-line output + if( !all ) { + cio_putchar( '\n' ); + } + + // sanity check - make sure we saw the correct number of table slots + if( (used + empty) != N_PROCS ) { + cio_printf( "Table size %d, used %d + empty %d = %d???\n", + N_PROCS, used, empty, used + empty ); + } +} + +/** +** Name: ptable_dump_counts +** +** Prints basic information about the process table (number of +** entries, number with each process state, etc.). +*/ +void ptable_dump_counts( void ) { + uint_t nstate[N_STATES] = { 0 }; + uint_t unknown = 0; + + int n = 0; + pcb_t *ptr = ptable; + while( n < N_PROCS ) { + if( ptr->state < 0 || ptr->state >= N_STATES ) { + ++unknown; + } else { + ++nstate[ptr->state]; + } + ++n; + ++ptr; + } + + cio_printf( "Ptable: %u ***", unknown ); + for( n = 0; n < N_STATES; ++n ) { + cio_printf( " %u %s", nstate[n], + state_str[n] != NULL ? state_str[n] : "???" ); + } + cio_putchar( '\n' ); +} diff --git a/kernel/sio.c b/kernel/sio.c new file mode 100644 index 0000000..a5c7b75 --- /dev/null +++ b/kernel/sio.c @@ -0,0 +1,694 @@ +/** +** @file sio.c +** +** @author Warren R. Carithers +** +** @brief SIO module +** +** For maximum compatibility from semester to semester, this code uses +** several "stand-in" type names and macros which should be defined +** in the accompanying "compat.h" header file if they're not part of +** the baseline system: +** +** standard-sized integer types: intN_t, uintN_t +** other types: PCBTYPE, QTYPE +** scheduler functions: SCHED, DISPATCH +** queue functions: QCREATE, QLENGTH, QDEQUE +** other functions: SLENGTH +** sio read queue: QNAME +** +** Our SIO scheme is very simple: +** +** Input: We maintain a buffer of incoming characters that haven't +** yet been read by processes. When a character comes in, if +** there is no process waiting for it, it goes in the buffer; +** otherwise, the first waiting process is awakeneda and it +** gets the character. +** +** When a process invokes readch(), if there is a character in +** the input buffer, the process gets it; otherwise, it is +** blocked until input appears +** +** Communication with system calls is via two routines. +** sio_readc() returns the first available character (if +** there is one), resetting the input variables if this was +** the last character in the buffer. If there are no +** characters in the buffer, sio_read() returns a -1 +** (presumably so the requesting process can be blocked). +** +** sio_read() copies the contents of the input buffer into +** a user-supplied buffer. It returns the number of characters +** copied. If there are no characters available, return a -1. +** +** Output: We maintain a buffer of outgoing characters that haven't +** yet been sent to the device, and an indication of whether +** or not we are in the middle of a transmit sequence. When +** an interrupt comes in, if there is another character to +** send we copy it to the transmitter buffer; otherwise, we +** end the transmit sequence. +** +** Communication with user processes is via three functions. +** sio_writec() writes a single character; sio_write() +** writes a sized buffer full of characters; sio_puts() +** prints a NUL-terminated string. If we are in the middle +** of a transmit sequence, all characters will be added +** to the output buffer (from where they will be sent +** automatically); otherwise, we send the first character +** directly, add the rest of the characters (if there are +** any) to the output buffer, and set the "sending" flag +** to indicate that we're expecting a transmitter interrupt. +*/ + +#define KERNEL_SRC + +// this should do all includes required for this OS +#include + +// all other framework includes are next +#include +#include +#include + +#include +#include + +/* +** PRIVATE DEFINITIONS +*/ + +#define BUF_SIZE 2048 + +/* +** PRIVATE GLOBALS +*/ + + // input character buffer +static char inbuffer[ BUF_SIZE ]; +static char *inlast; +static char *innext; +static uint32_t incount; + + // output character buffer +static char outbuffer[ BUF_SIZE ]; +static char *outlast; +static char *outnext; +static uint32_t outcount; + + // output control flag +static int sending; + + // interrupt register status +static uint8_t ier; + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +// queue for read-blocked processes +#ifdef QNAME +QTYPE QNAME; +#endif + +/* +** PRIVATE FUNCTIONS +*/ + +/** +** sio_isr(vector,ecode) +** +** Interrupt handler for the SIO module. Handles all pending +** events (as described by the SIO controller). +** +** @param vector The interrupt vector number for this interrupt +** @param ecode The error code associated with this interrupt +*/ +static void sio_isr( int vector, int ecode ) { + int ch; + +#if TRACING_SIO_ISR + cio_puts( "SIO: int:" ); +#endif + // + // Must process all pending events; loop until the IRR + // says there's nothing else to do. + // + + for(;;) { + + // get the "pending event" indicator + int iir = inb( UA4_IIR ) & UA4_IIR_INT_PRI_MASK; + + // process this event + switch( iir ) { + + case UA4_IIR_LINE_STATUS: + // shouldn't happen, but just in case.... + cio_printf( "** SIO int, LSR = %02x\n", inb(UA4_LSR) ); + break; + + case UA4_IIR_RX: +#if TRACING_SIO_ISR + cio_puts( " RX" ); +#endif + // get the character + ch = inb( UA4_RXD ); + if( ch == '\r' ) { // map CR to LF + ch = '\n'; + } +#if TRACING_SIO_ISR + cio_printf( " ch %02x", ch ); +#endif + +#ifdef QNAME + // + // If there is a waiting process, this must be + // the first input character; give it to that + // process and awaken the process. + // + + if( !QEMPTY(QNAME) ) { + PCBTYPE *pcb; + + QDEQUE( QNAME, pcb ); + // make sure we got a non-NULL result + assert( pcb ); + + // return char via arg #2 and count in EAX + char *buf = (char *) ARG(pcb,2); + *buf = ch & 0xff; + RET(pcb) = 1; + SCHED( pcb ); + + } else { +#endif /* QNAME */ + + // + // Nobody waiting - add to the input buffer + // if there is room, otherwise just ignore it. + // + + if( incount < BUF_SIZE ) { + *inlast++ = ch; + ++incount; + } + +#ifdef QNAME + } +#endif /* QNAME */ + break; + + case UA5_IIR_RX_FIFO: + // shouldn't happen, but just in case.... + ch = inb( UA4_RXD ); + cio_printf( "** SIO FIFO timeout, RXD = %02x\n", ch ); + break; + + case UA4_IIR_TX: +#if TRACING_SIO_ISR + cio_puts( " TX" ); +#endif + // if there is another character, send it + if( sending && outcount > 0 ) { +#if TRACING_SIO_ISR + cio_printf( " ch %02x", *outnext ); +#endif + outb( UA4_TXD, *outnext ); + ++outnext; + // wrap around if necessary + if( outnext >= (outbuffer + BUF_SIZE) ) { + outnext = outbuffer; + } + --outcount; +#if TRACING_SIO_ISR + cio_printf( " (outcount %d)", outcount ); +#endif + } else { +#if TRACING_SIO_ISR + cio_puts( " EOS" ); +#endif + // no more data - reset the output vars + outcount = 0; + outlast = outnext = outbuffer; + sending = 0; + // disable TX interrupts + sio_disable( SIO_TX ); + } + break; + + case UA4_IIR_NO_INT: +#if TRACING_SIO_ISR + cio_puts( " EOI\n" ); +#endif + // nothing to do - tell the PIC we're done + outb( PIC1_CMD, PIC_EOI ); + return; + + case UA4_IIR_MODEM_STATUS: + // shouldn't happen, but just in case.... + cio_printf( "** SIO int, MSR = %02x\n", inb(UA4_MSR) ); + break; + + default: + // uh-oh.... + sprint( b256, "sio isr: IIR %02x\n", ((uint32_t) iir) & 0xff ); + PANIC( 0, b256 ); + } + + } + + // should never reach this point! + assert( false ); +} + +/* +** PUBLIC FUNCTIONS +*/ + +/** +** sio_init() +** +** Initialize the UART chip. +*/ +void sio_init( void ) { + +#if TRACING_INIT + cio_puts( " Sio" ); +#endif + + /* + ** Initialize SIO variables. + */ + + memclr( (void *) inbuffer, sizeof(inbuffer) ); + inlast = innext = inbuffer; + incount = 0; + + memclr( (void *) outbuffer, sizeof(outbuffer) ); + outlast = outnext = outbuffer; + outcount = 0; + sending = 0; + + // queue of read-blocked processes + QCREATE( QNAME ); + + /* + ** Next, initialize the UART. + ** + ** Initialize the FIFOs + ** + ** this is a bizarre little sequence of operations + */ + + outb( UA5_FCR, 0x20 ); + outb( UA5_FCR, UA5_FCR_FIFO_RESET ); // 0x00 + outb( UA5_FCR, UA5_FCR_FIFO_EN ); // 0x01 + outb( UA5_FCR, UA5_FCR_FIFO_EN | UA5_FCR_RXSR ); // 0x03 + outb( UA5_FCR, UA5_FCR_FIFO_EN | UA5_FCR_RXSR | UA5_FCR_TXSR ); // 0x07 + + /* + ** disable interrupts + ** + ** note that we leave them disabled; sio_enable() must be + ** called to switch them back on + */ + + outb( UA4_IER, 0 ); + ier = 0; + + /* + ** select the divisor latch registers and set the data rate + */ + + outb( UA4_LCR, UA4_LCR_DLAB ); + outb( UA4_DLL, BAUD_LOW_BYTE( DL_BAUD_9600 ) ); + outb( UA4_DLM, BAUD_HIGH_BYTE( DL_BAUD_9600 ) ); + + /* + ** deselect the latch registers, by setting the data + ** characteristics in the LCR + */ + + outb( UA4_LCR, UA4_LCR_WLS_8 | UA4_LCR_1_STOP_BIT | UA4_LCR_NO_PARITY ); + + /* + ** Set the ISEN bit to enable the interrupt request signal, + ** and the DTR and RTS bits to enable two-way communication. + */ + + outb( UA4_MCR, UA4_MCR_ISEN | UA4_MCR_DTR | UA4_MCR_RTS ); + + /* + ** Install our ISR + */ + + install_isr( VEC_COM1, sio_isr ); +} + +/** +** sio_enable() +** +** Enable SIO interrupts +** +** usage: uint8_t old = sio_enable( uint8_t which ) +** +** @param which Bit mask indicating which interrupt(s) to enable +** +** @return the prior IER setting +*/ +uint8_t sio_enable( uint8_t which ) { + uint8_t old; + + // remember the current status + + old = ier; + + // figure out what to enable + + if( which & SIO_TX ) { + ier |= UA4_IER_TX_IE; + } + + if( which & SIO_RX ) { + ier |= UA4_IER_RX_IE; + } + + // if there was a change, make it + + if( old != ier ) { + outb( UA4_IER, ier ); + } + + // return the prior settings + + return( old ); +} + +/** +** sio_disable() +** +** Disable SIO interrupts +** +** usage: uint8_t old = sio_disable( uint8_t which ) +** +** @param which Bit mask indicating which interrupt(s) to disable +** +** @return the prior IER setting +*/ +uint8_t sio_disable( uint8_t which ) { + uint8_t old; + + // remember the current status + + old = ier; + + // figure out what to disable + + if( which & SIO_TX ) { + ier &= ~UA4_IER_TX_IE; + } + + if( which & SIO_RX ) { + ier &= ~UA4_IER_RX_IE; + } + + // if there was a change, make it + + if( old != ier ) { + outb( UA4_IER, ier ); + } + + // return the prior settings + + return( old ); +} + +/** +** sio_inq_length() +** +** Get the input queue length +** +** usage: int num = sio_inq_length() +** +** @return the count of characters still in the input queue +*/ +int sio_inq_length( void ) { + return( incount ); +} + +/** +** sio_readc() +** +** Get the next input character +** +** usage: int ch = sio_readc() +** +** @return the next character, or -1 if no character is available +*/ +int sio_readc( void ) { + int ch; + + // assume there is no character available + ch = -1; + + // + // If there is a character, return it + // + + if( incount > 0 ) { + + // take it out of the input buffer + ch = ((int)(*innext++)) & 0xff; + --incount; + + // reset the buffer variables if this was the last one + if( incount < 1 ) { + inlast = innext = inbuffer; + } + + } + + return( ch ); + +} + +/** +** sio_read(buf,length) +** +** Read the entire input buffer into a user buffer of a specified size +** +** usage: int num = sio_read( char *buffer, int length ) +** +** @param buf The destination buffer +** @param length Length of the buffer +** +** @return the number of bytes copied, or 0 if no characters were available +*/ + +int sio_read( char *buf, int length ) { + char *ptr = buf; + int copied = 0; + + // if there are no characters, just return 0 + + if( incount < 1 ) { + return( 0 ); + } + + // + // We have characters. Copy as many of them into the user + // buffer as will fit. + // + + while( incount > 0 && copied < length ) { + *ptr++ = *innext++ & 0xff; + if( innext > (inbuffer + BUF_SIZE) ) { + innext = inbuffer; + } + --incount; + ++copied; + } + + // reset the input buffer if necessary + + if( incount < 1 ) { + inlast = innext = inbuffer; + } + + // return the copy count + + return( copied ); +} + + +/** +** sio_writec( ch ) +** +** Write a character to the serial output +** +** usage: sio_writec( int ch ) +** +** @param ch Character to be written (in the low-order 8 bits) +*/ +void sio_writec( int ch ){ + + + // + // Must do LF -> CRLF mapping + // + + if( ch == '\n' ) { + sio_writec( '\r' ); + } + + // + // If we're currently transmitting, just add this to the buffer + // + + if( sending ) { + *outlast++ = ch; + ++outcount; + return; + } + + // + // Not sending - must prime the pump + // + + sending = 1; + outb( UA4_TXD, ch ); + + // Also must enable transmitter interrupts + + sio_enable( SIO_TX ); + +} + +/** +** sio_write( buffer, length ) +** +** Write a buffer of characters to the serial output +** +** usage: int num = sio_write( const char *buffer, int length ) +** +** @param buffer Buffer containing characters to write +** @param length Number of characters to write +** +** @return the number of characters copied into the SIO output buffer +*/ +int sio_write( const char *buffer, int length ) { + int first = *buffer; + const char *ptr = buffer; + int copied = 0; + + // + // If we are currently sending, we want to append all + // the characters to the output buffer; else, we want + // to append all but the first character, and then use + // sio_writec() to send the first one out. + // + + if( !sending ) { + ptr += 1; + copied++; + } + + while( copied < length && outcount < BUF_SIZE ) { + *outlast++ = *ptr++; + // wrap around if necessary + if( outlast >= (outbuffer + BUF_SIZE) ) { + outlast = outbuffer; + } + ++outcount; + ++copied; + } + + // + // We use sio_writec() to send out the first character, + // as it will correctly set all the other necessary + // variables for us. + // + + if( !sending ) { + sio_writec( first ); + } + + // Return the transfer count + + + return( copied ); + +} + +/** +** sio_puts( buf ) +** +** Write a NUL-terminated buffer of characters to the serial output +** +** usage: int num = sio_puts( const char *buffer ) +** +** @param buffer The buffer containing a NUL-terminated string +** +** @return the count of bytes transferred +*/ +int sio_puts( const char *buffer ) { + int n; // must be outside the loop so we can return it + + n = SLENGTH( buffer ); + sio_write( buffer, n ); + + return( n ); +} + +/** +** sio_dump( full ) +** +** dump the contents of the SIO buffers to the console +** +** usage: sio_dump(true) or sio_dump(false) +** +** @param full Boolean indicating whether or not a "full" dump +** is being requested (which includes the contents +** of the queues) +*/ + +void sio_dump( bool_t full ) { + int n; + char *ptr; + + // dump basic info into the status region + + cio_printf_at( 48, 0, + "SIO: IER %02x (%c%c%c) in %d ot %d", + ((uint32_t)ier) & 0xff, sending ? '*' : '.', + (ier & UA4_IER_TX_IE) ? 'T' : 't', + (ier & UA4_IER_RX_IE) ? 'R' : 'r', + incount, outcount ); + + // if we're not doing a full dump, stop now + + if( !full ) { + return; + } + + // also want the queue contents, but we'll + // dump them into the scrolling region + + if( incount ) { + cio_puts( "SIO input queue: \"" ); + ptr = innext; + for( n = 0; n < incount; ++n ) { + put_char_or_code( *ptr++ ); + } + cio_puts( "\"\n" ); + } + + if( outcount ) { + cio_puts( "SIO output queue: \"" ); + cio_puts( " ot: \"" ); + ptr = outnext; + for( n = 0; n < outcount; ++n ) { + put_char_or_code( *ptr++ ); + } + cio_puts( "\"\n" ); + } +} diff --git a/kernel/startup.S b/kernel/startup.S new file mode 100644 index 0000000..1cae13c --- /dev/null +++ b/kernel/startup.S @@ -0,0 +1,153 @@ +/* +** @file startup.S +** +** @author Jon Coles +** @authors Warren R. Carithers, K. Reek +** +** SP startup code. +** +** This code prepares the various registers for execution of +** the program. It sets up all the segment registers and the +** runtime stack. By the time this code is running, we're in +** protected mode already. +*/ + +#define KERNEL_SRC +#define ASM_SRC + + .arch i386 + +#include +#include +#include +#include +#include + +/* +** Configuration options - define in Makefile +** +** CLEAR_BSS include code to clear all BSS space +** OS_CONFIG OS-related (vs. just standalone) variations +*/ + +/* +** A symbol for locating the beginning of the code. +*/ + .globl begtext + + .text +begtext: + +/* +** The entry point. When we get here, we have just entered protected +** mode, so all the segment registers are incorrect except for CS. +*/ + .globl _start + +_start: + cli /* seems to be reset on entry to p. mode */ + movb $NMI_ENABLE, %al /* re-enable NMIs (bootstrap */ + outb $CMOS_ADDR /* turned them off) */ + +/* +** Set the data and stack segment registers (code segment register +** was set by the long jump that switched us into protected mode). +*/ + xorl %eax, %eax /* clear EAX */ + movw $GDT_DATA, %ax /* GDT entry #3 - data segment */ + movw %ax, %ds /* for all four data segment registers */ + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + movw $GDT_STACK, %ax /* entry #4 is the stack segment */ + movw %ax, %ss + + movl $TARGET_STACK, %esp /* set up the system stack pointer */ + +#ifdef CLEAR_BSS +/* +** Zero the BSS segment +** +** These symbols are defined automatically by the linker, but they're +** defined at their virtual addresses rather than their physical addresses, +** and we haven't enabled paging yet. +*/ + .globl __bss_start, _end + + movl $V2P(__bss_start), %edi +clearbss: + movl $0, (%edi) + addl $4, %edi + cmpl $V2P(_end), %edi + jb clearbss +#endif /* CLEAR_BSS */ + +/* +** Enable paging. We use "large" pages for the initial page directory +** so that a one-level hierarchy will work for us. Once we have set +** up our memory freelist, we'll create a two-level hierarchy using +** "normal" 4KB pages. +*/ + # enable large pages + movl %cr4, %eax + orl $(CR4_PSE), %eax + movl %eax, %cr4 + + # set the page directory + .globl firstpdir + movl $(V2P(firstpdir)+0x1000), %eax + movl %eax, %cr3 + + # turn on paging + movl %cr0, %eax + orl $(CR0_PG), %eax + movl %eax, %cr0 + + # reset our stack pointer + movl $(kstack + SZ_KSTACK), %esp + + # set the initial frame pointer + xorl %ebp, %ebp + +/* +** Call the system initialization routine, and switch to +** executing at high addresses. We use an indirect jump +** here to avoid getting a PC-relative 'jmp' instruction. +** +** Alternate idea: push the address of isr_restore +** and just do an indirect jump? +*/ + .globl main + + movl $main, %eax + call *%eax + +/* +** At this point, main() must have created the first user +** process, and we're ready to shift into user mode. The user +** stack for that process must have the initial context in it; +** we treat this as a "return from interrupt" event, and just +** transfer to the code that restores the user context. +*/ + + .globl isr_restore + jmp isr_restore + + .data + +/* +** Define the kernel stack here, at a multiple-of-16 address +*/ + .p2align 4 + .globl kstack +kstack: .space SZ_KSTACK, 0 + +/* +** Define the initial kernel ESP here, as well. It should point +** to the first byte after the stack. +*/ + + .globl kernel_esp +kernel_esp: + .long kstack + SZ_KSTACK diff --git a/kernel/support.c b/kernel/support.c new file mode 100644 index 0000000..d48ce59 --- /dev/null +++ b/kernel/support.c @@ -0,0 +1,279 @@ +/* +** SCCS ID: @(#)support.c 2.6 1/22/25 +** +** @file support.c +** +** @author 4003-506 class of 20003 +** @authors K. Reek, Warren R. Carithers +** +** Miscellaneous system initialization functions, interrupt +** support routines, and data structures. +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* +** Global variables and local data types. +*/ + +/* +** This is the table that contains pointers to the C-language ISR for +** each interrupt. These functions are called from the isr stub based +** on the interrupt number. +*/ +void ( *isr_table[ 256 ] )( int vector, int code ); + +/* +** Format of an IDT entry. +*/ +typedef struct { + short offset_15_0; + short segment_selector; + short flags; + short offset_31_16; +} IDT_Gate; + +/* +** LOCAL ROUTINES - not intended to be used outside this module. +*/ + +/** +** unexpected_handler +** +** This routine catches interrupts that we do not expect to ever occur. +** It handles them by (optionally) reporting them and then calling panic(). +** +** @param vector vector number for the interrupt that occurred +** @param code error code, or a dummy value +** +** Does not return. +*/ +#ifdef RPT_INT_UNEXP +/* add any header includes you need here */ +#endif +static void unexpected_handler( int vector, int code ) { +#ifdef RPT_INT_UNEXP + cio_printf( "\n** UNEXPECTED vector %d code %d\n", vector, code ); +#endif + panic( "Unexpected interrupt" ); +} + +/** +** default_handler +** +** Default handler for interrupts we expect may occur but are not +** handling (yet). We just reset the PIC and return. +** +** @param vector vector number for the interrupt that occurred +** @param code error code, or a dummy value +*/ +static void default_handler( int vector, int code ) { +#ifdef RPT_INT_UNEXP + cio_printf( "\n** vector %d code %d\n", vector, code ); +#endif + if( vector >= 0x20 && vector < 0x30 ) { + if( vector > 0x27 ) { + // must also ACK the secondary PIC + outb( PIC2_CMD, PIC_EOI ); + } + outb( PIC1_CMD, PIC_EOI ); + } else { + /* + ** All the "expected" interrupts will be handled by the + ** code above. If we get down here, the isr table may + ** have been corrupted. Print a message and don't return. + */ + panic( "Unexpected \"expected\" interrupt!" ); + } +} + +/** +** mystery_handler +** +** Default handler for the "mystery" interrupt that comes through vector +** 0x27. This is a non-repeatable interrupt whose source has not been +** identified, but it appears to be the famous "spurious level 7 interrupt" +** source. +** +** @param vector vector number for the interrupt that occurred +** @param code error code, or a dummy value +*/ +static void mystery_handler( int vector, int code ) { +#if defined(RPT_INT_MYSTERY) || defined(RPT_INT_UNEXP) + cio_printf( "\nMystery interrupt!\nVector=0x%02x, code=%d\n", + vector, code ); +#endif + outb( PIC1_CMD, PIC_EOI ); +} + +/** +** init_pic +** +** Initialize the 8259 Programmable Interrupt Controller. +*/ +static void init_pic( void ) { + /* + ** ICW1: start the init sequence, update ICW4 + */ + outb( PIC1_CMD, PIC_CW1_INIT | PIC_CW1_NEED4 ); + outb( PIC2_CMD, PIC_CW1_INIT | PIC_CW1_NEED4 ); + + /* + ** ICW2: primary offset of 0x20 in the IDT, secondary offset of 0x28 + */ + outb( PIC1_DATA, PIC1_CW2_VECBASE ); + outb( PIC2_DATA, PIC2_CW2_VECBASE ); + + /* + ** ICW3: secondary attached to line 2 of primary, bit mask is 00000100 + ** secondary id is 2 + */ + outb( PIC1_DATA, PIC1_CW3_SEC_IRQ2 ); + outb( PIC2_DATA, PIC2_CW3_SEC_ID ); + + /* + ** ICW4: want 8086 mode, not 8080/8085 mode + */ + outb( PIC1_DATA, PIC_CW4_PM86 ); + outb( PIC2_DATA, PIC_CW4_PM86 ); + + /* + ** OCW1: allow interrupts on all lines + */ + outb( PIC1_DATA, PIC_MASK_NONE ); + outb( PIC2_DATA, PIC_MASK_NONE ); +} + +/** +** set_idt_entry +** +** Construct an entry in the IDT +** +** @param entry the vector number of the interrupt +** @param handler ISR address to be put into the IDT entry +** +** Note: generally, the handler invoked from the IDT will be a "stub" +** that calls the second-level C handler via the isr_table array. +*/ +static void set_idt_entry( int entry, void ( *handler )( void ) ) { + IDT_Gate *g = (IDT_Gate *)IDT_ADDR + entry; + + g->offset_15_0 = (int)handler & 0xffff; + g->segment_selector = 0x0010; + g->flags = IDT_PRESENT | IDT_DPL_0 | IDT_INT32_GATE; + g->offset_31_16 = (int)handler >> 16 & 0xffff; +} + +/** +** Name: init_idt +** +** Initialize the Interrupt Descriptor Table (IDT). This makes each of +** the entries in the IDT point to the isr stub for that entry, and +** installs a default handler in the handler table. Temporary handlers +** are then installed for those interrupts we may get before a real +** handler is set up. +*/ +static void init_idt( void ) { + int i; + extern void ( *isr_stub_table[ 256 ] )( void ); + + /* + ** Make each IDT entry point to the stub for that vector. Also + ** make each entry in the ISR table point to the default handler. + */ + for ( i=0; i < 256; i++ ) { + set_idt_entry( i, isr_stub_table[ i ] ); + install_isr( i, unexpected_handler ); + } + + /* + ** Install the handlers for interrupts that have (or will have) a + ** specific handler. Comments indicate which module init function + ** will eventually install the "real" handler. + */ + + install_isr( VEC_KBD, default_handler ); // cio_init() + install_isr( VEC_COM1, default_handler ); // sio_init() + install_isr( VEC_TIMER, default_handler ); // clk_init() + install_isr( VEC_SYSCALL, default_handler ); // sys_init() + install_isr( VEC_PAGE_FAULT, default_handler ); // vm_init() + + install_isr( VEC_MYSTERY, mystery_handler ); +} + +/* +** END OF LOCAL ROUTINES. +** +** Full documentation for globally-visible routines is in the corresponding +** header file. +*/ + +/* +** panic +** +** Called when we find an unrecoverable error. +*/ +void panic( char *reason ) { + __asm__( "cli" ); + cio_printf( "\nPANIC: %s\nHalting...", reason ); + for(;;) { + ; + } +} + +/* +** init_interrupts +** +** (Re)initilizes the interrupt system. +*/ +void init_interrupts( void ) { + init_idt(); + init_pic(); +} + +/* +** install_isr +** +** Installs a second-level handler for a specific interrupt. +*/ +void (*install_isr( int vector, + void (*handler)(int,int) ) ) ( int, int ) { + + void ( *old_handler )( int vector, int code ); + + old_handler = isr_table[ vector ]; + isr_table[ vector ] = handler; + return old_handler; +} + +/* +** Name: delay +** +** Notes: The parameter to the delay() function is ambiguous; it +** purports to indicate a delay length, but that isn't really tied +** to any real-world time measurement. +** +** On the original systems we used (dual 500MHz Intel P3 CPUs), each +** "unit" was approximately one tenth of a second, so delay(10) would +** delay for about one second. +** +** On the current machines (Intel Core i5-7500), delay(100) is about +** 2.5 seconds, so each "unit" is roughly 0.025 seconds. +** +** Ultimately, just remember that DELAY VALUES ARE APPROXIMATE AT BEST. +*/ +void delay( int length ) { + + while( --length >= 0 ) { + for( int i = 0; i < 10000000; ++i ) + ; + } +} diff --git a/kernel/syscalls.c b/kernel/syscalls.c new file mode 100644 index 0000000..7176cda --- /dev/null +++ b/kernel/syscalls.c @@ -0,0 +1,829 @@ +/** +** @file syscalls.c +** +** @author CSCI-452 class of 20245 +** +** @brief System call implementations +*/ + +#define KERNEL_SRC + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** PRIVATE DEFINITIONS +*/ + +/* +** Macros to simplify tracing a bit +** +** TRACING_SYSCALLS and TRACING_SYSRETS are defined in debug.h, +** controlled by the TRACE ** macro. If not tracing these, SYSCALL_ENTER +** is a no-op, and SYSCALL_EXIT just does a return. +*/ + +#if TRACING_SYSCALLS + +#define SYSCALL_ENTER(x) do { \ + cio_printf( "--> %s, pid %08x", __func__, (uint32_t) (x) ); \ + } while(0) + +#else + +#define SYSCALL_ENTER(x) /* */ + +#endif /* TRACING_SYSCALLS */ + +#if TRACING_SYSRETS + +#define SYSCALL_EXIT(x) do { \ + cio_printf( "<-- %s %08x\n", __func__, (uint32_t) (x) ); \ + return; \ + } while(0) + +#else + +#define SYSCALL_EXIT(x) return + +#endif /* TRACING_SYSRETS */ + +/* +** PRIVATE DATA TYPES +*/ + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +/* +** IMPLEMENTATION FUNCTIONS +*/ + +// a macro to simplify syscall entry point specification +// we don't declare these static because we may want to call +// some of them from other parts of the kernel +#define SYSIMPL(x) void sys_##x( pcb_t * pcb ) + +/* +** Second-level syscall handlers +** +** All have this prototype: +** +** static void sys_NAME( pcb_t *pcb ); +** +** where the parameter 'pcb' is a pointer to the PCB of the process +** making the system call. +** +** Values being returned to the user are placed into the EAX +** field in the context save area for that process. +*/ + +/** +** sys_exit - terminate the calling process +** +** Implements: +** void exit( int32_t status ); +** +** Does not return +*/ +SYSIMPL(exit) { + + // sanity check + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // retrieve the exit status of this process + pcb->exit_status = (int32_t) ARG(pcb,1); + + // now, we need to do the following: + // reparent any children of this process and wake up init if need be + // find this process' parent and wake it up if it's waiting + + pcb_zombify( pcb ); + + // pick a new winner + dispatch(); + + SYSCALL_EXIT( 0 ); +} + +/** +** sys_waitpid - wait for a child process to terminate +** +** Implements: +** int waitpid( uint_t pid, int32_t *status ); +** +** Blocks the calling process until the specified child (or any child) +** of the caller terminates. Intrinsic return is the PID of the child that +** terminated, or an error code; on success, returns the child's termination +** status via 'status' if that pointer is non-NULL. +*/ +SYSIMPL(waitpid) { + + // sanity check + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + /* + ** We need to do two things here: (1) find out whether or + ** not this process has any children in the system, and (2) + ** find out whether the desired child (or any child, if the + ** target PID is 0) has terminated. + ** + ** To do this, we loop until we find a the requested PID or + ** a Zombie child process, or have gone through all of the + ** slots in the process table. + ** + ** If the target PID is 0, we don't care which child process + ** we reap here; there could be several, but we only need to + ** find one. + */ + + // verify that we aren't looking for ourselves! + uint_t target = ARG(pcb,1); + + if( target == pcb->pid ) { + RET(pcb) = E_BAD_PARAM; + SYSCALL_EXIT( E_BAD_PARAM ); + } + + // Good. Now, figure out what we're looking for. + + pcb_t *child = NULL; + + if( target != 0 ) { + + // we're looking for a specific child + child = pcb_find_pid( target ); + + if( child != NULL ) { + + // found the process; is it one of our children: + if( child->parent != pcb ) { + // NO, so we can't wait for it + RET(pcb) = E_BAD_PARAM; + SYSCALL_EXIT( E_BAD_PARAM ); + } + + // yes! is this one ready to be collected? + if( child->state != STATE_ZOMBIE ) { + // no, so we'll have to block for now + child = NULL; + } + + } else { + + // no such child + RET(pcb) = E_BAD_PARAM; + SYSCALL_EXIT( E_BAD_PARAM ); + + } + + } else { + + // looking for any child + + // we need to find a process that is our child + // and has already exited + + child = NULL; + bool_t found = false; + + // unfortunately, we can't stop at the first child, + // so we need to do the iteration ourselves + register pcb_t *curr = ptable; + + for( int i = 0; i < N_PROCS; ++i, ++curr ) { + + if( curr->parent == pcb ) { + + // found one! + found = true; + + // has it already exited? + if( curr->state == STATE_ZOMBIE ) { + // yes, so we're done here + child = curr; + break; + } + } + } + + if( !found ) { + // got through the loop without finding a child! + RET(pcb) = E_NO_CHILDREN; + SYSCALL_EXIT( E_NO_CHILDREN ); + } + + } + + /* + ** At this point, one of these situations is true: + ** + ** * we are looking for a specific child and found it + ** * we are looking for any child and found one + ** + ** Either way, 'child' will be non-NULL if the selected + ** process has already become a Zombie. If that's the + ** case, we collect its status and clean it up; otherwise, + ** we block this process. + */ + + // did we find one to collect? + if( child == NULL ) { + + // no - mark the parent as "Waiting" + pcb->state = STATE_WAITING; + assert( pcb_queue_insert(waiting,pcb) == SUCCESS ); + + // select a new current process + dispatch(); + SYSCALL_EXIT( (uint32_t) current ); + } + + // found a Zombie; collect its information and clean it up + RET(pcb) = child->pid; + + // get "status" pointer from parent + int32_t *stat = (int32_t *) ARG(pcb,2); + + // if stat is NULL, the parent doesn't want the status + if( stat != NULL ) { + // ******************************************************** + // ** Potential VM issue here! This code assigns the exit + // ** status into a variable in the parent's address space. + // ** This works in the baseline because we aren't using + // ** any type of memory protection. If address space + // ** separation is implemented, this code will very likely + // ** STOP WORKING, and will need to be fixed. + // ******************************************************** + *stat = child->exit_status; + } + + // clean up the child + pcb_cleanup( child ); + + SYSCALL_EXIT( RET(pcb) ); +} + +/** +** sys_fork - create a new process +** +** Implements: +** int fork( void ); +** +** Creates a new process that is a duplicate of the calling process. +** Returns the child's PID to the parent, and 0 to the child, on success; +** else, returns an error code to the parent. +*/ +SYSIMPL(fork) { + + // sanity check + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // Make sure there's room for another process! + pcb_t *new; + if( pcb_alloc(&new) != SUCCESS || new == NULL ) { + RET(pcb) = E_NO_PROCS; + SYSCALL_EXIT( RET(pcb) ); + } + + // duplicate the memory image of the parent + int status = user_duplicate( new, pcb ); + if( status != SUCCESS ) { + pcb_free( new ); + RET(pcb) = status; + SYSCALL_EXIT( status ); + } + + // Set the child's identity. + new->pid = next_pid++; + new->parent = pcb; + new->state = STATE_NEW; + + // replicate other things inherited from the parent + new->priority = pcb->priority; + + // Set the return values for the two processes. + RET(pcb) = new->pid; + RET(new) = 0; + + // Schedule the child, and let the parent continue. + schedule( new ); + + SYSCALL_EXIT( new->pid ); +} + +/** +** sys_exec - replace the memory image of a process +** +** Implements: +** void exec( uint_t what, char **args ); +** +** Replaces the memory image of the calling process with that of the +** indicated program. +** +** Returns only on failure. +*/ +SYSIMPL(exec) +{ + // sanity check + assert( pcb != NULL ); + + uint_t what = ARG(pcb,1); + const char **args = (const char **) ARG(pcb,2); + + SYSCALL_ENTER( pcb->pid ); + + // locate the requested program + prog_t *prog = user_locate( what ); + if( prog == NULL ) { + RET(pcb) = E_NOT_FOUND; + SYSCALL_EXIT( E_NOT_FOUND ); + } + + // we have located the program, but before we can load it, + // we need to clean up the existing VM hierarchy + vm_free( pcb->pdir ); + pcb->pdir = NULL; + + // "load" it and set up the VM tables for this process + int status = user_load( prog, pcb, args ); + if( status != SUCCESS ) { + RET(pcb) = status; + SYSCALL_EXIT( status ); + } + + /* + ** Decision: + ** (A) schedule this process and dispatch another, + ** (B) let this one continue in its current time slice + ** (C) reset this one's time slice and let it continue + ** + ** We choose option A. + ** + ** If scheduling the process fails, the exec() has failed. However, + ** all trace of the old process is gone by now, so we can't return + ** an error status to it. + */ + + schedule( pcb ); + + dispatch(); +} + +/** +** sys_read - read into a buffer from an input channel +** +** Implements: +** int read( uint_t chan, void *buffer, uint_t length ); +** +** Reads up to 'length' bytes from 'chan' into 'buffer'. Returns the +** count of bytes actually transferred. +*/ +SYSIMPL(read) { + + // sanity check + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // grab the arguments + uint_t chan = ARG(pcb,1); + char *buf = (char *) ARG(pcb,2); + uint_t len = ARG(pcb,3); + + // if the buffer is of length 0, we're done! + if( len == 0 ) { + RET(pcb) = 0; + SYSCALL_EXIT( 0 ); + } + + // try to get the next character(s) + int n = 0; + + if( chan == CHAN_CIO ) { + + // console input is non-blocking + if( cio_input_queue() < 1 ) { + RET(pcb) = 0; + SYSCALL_EXIT( 0 ); + } + // at least one character + n = cio_gets( buf, len ); + RET(pcb) = n; + SYSCALL_EXIT( n ); + + } else if( chan == CHAN_SIO ) { + + // SIO input is blocking, so if there are no characters + // available, we'll block this process + n = sio_read( buf, len ); + RET(pcb) = n; + SYSCALL_EXIT( n ); + + } + + // bad channel code + RET(pcb) = E_BAD_PARAM; + SYSCALL_EXIT( E_BAD_PARAM ); +} + +/** +** sys_write - write from a buffer to an output channel +** +** Implements: +** int write( uint_t chan, const void *buffer, uint_t length ); +** +** Writes 'length' bytes from 'buffer' to 'chan'. Returns the +** count of bytes actually transferred. +*/ +SYSIMPL(write) { + + // sanity check + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // grab the parameters + uint_t chan = ARG(pcb,1); + char *buf = (char *) ARG(pcb,2); + uint_t length = ARG(pcb,3); + + // this is almost insanely simple, but it does separate the + // low-level device access fromm the higher-level syscall implementation + + // assume we write the indicated amount + int rval = length; + + // simplest case + if( length >= 0 ) { + + if( chan == CHAN_CIO ) { + + cio_write( buf, length ); + + } else if( chan == CHAN_SIO ) { + + sio_write( buf, length ); + + } else { + + rval = E_BAD_CHAN; + + } + + } + + RET(pcb) = rval; + + SYSCALL_EXIT( rval ); +} + +/** +** sys_getpid - returns the PID of the calling process +** +** Implements: +** uint_t getpid( void ); +*/ +SYSIMPL(getpid) { + + // sanity check! + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // return the time + RET(pcb) = pcb->pid; +} + +/** +** sys_getppid - returns the PID of the parent of the calling process +** +** Implements: +** uint_t getppid( void ); +*/ +SYSIMPL(getppid) { + + // sanity check! + assert( pcb != NULL ); + assert( pcb->parent != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // return the time + RET(pcb) = pcb->parent->pid; +} + +/** +** sys_gettime - returns the current system time +** +** Implements: +** uint32_t gettime( void ); +*/ +SYSIMPL(gettime) { + + // sanity check! + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // return the time + RET(pcb) = system_time; +} + +/** +** sys_getprio - the scheduling priority of the calling process +** +** Implements: +** int getprio( void ); +*/ +SYSIMPL(getprio) { + + // sanity check! + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // return the time + RET(pcb) = pcb->priority; +} + +/** +** sys_setprio - sets the scheduling priority of the calling process +** +** Implements: +** int setprio( int new ); +*/ +SYSIMPL(setprio) { + + // sanity check! + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // remember the old priority + int old = pcb->priority; + + // set the priority + pcb->priority = ARG(pcb,1); + + // return the old value + RET(pcb) = old; +} + +/** +** sys_kill - terminate a process with extreme prejudice +** +** Implements: +** int32_t kill( uint_t pid ); +** +** Marks the specified process (or the calling process, if PID is 0) +** as "killed". Returns 0 on success, else an error code. +*/ +SYSIMPL(kill) { + + // sanity check + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // who is the victim? + uint_t pid = ARG(pcb,1); + + // if it's this process, convert this into a call to exit() + if( pid == pcb->pid ) { + pcb->exit_status = EXIT_KILLED; + pcb_zombify( pcb ); + dispatch(); + SYSCALL_EXIT( EXIT_KILLED ); + } + + // must be a valid "ordinary user" PID + // QUESTION: what if it's the idle process? + if( pid < FIRST_USER_PID ) { + RET(pcb) = E_FAILURE; + SYSCALL_EXIT( E_FAILURE ); + } + + // OK, this is an acceptable victim; see if it exists + pcb_t *victim = pcb_find_pid( pid ); + if( victim == NULL ) { + // nope! + RET(pcb) = E_NOT_FOUND; + SYSCALL_EXIT( E_NOT_FOUND ); + } + + // must have a state that is possible + assert( victim->state >= FIRST_VIABLE && victim->state < N_STATES ); + + // how we perform the kill depends on the victim's state + int32_t status = SUCCESS; + + switch( victim->state ) { + + case STATE_KILLED: // FALL THROUGH + case STATE_ZOMBIE: + // you can't kill it if it's already dead + RET(pcb) = SUCCESS; + break; + + case STATE_READY: // FALL THROUGH + case STATE_SLEEPING: // FALL THROUGH + case STATE_BLOCKED: // FALL THROUGH + // here, the process is on a queue somewhere; mark + // it as "killed", and let the scheduler deal with it + victim->state = STATE_KILLED; + RET(pcb) = SUCCESS; + break; + + case STATE_RUNNING: + // we have met the enemy, and it is us! + pcb->exit_status = EXIT_KILLED; + pcb_zombify( pcb ); + status = EXIT_KILLED; + // we need a new current process + dispatch(); + break; + + case STATE_WAITING: + // similar to the 'running' state, but we don't need + // to dispatch a new process + victim->exit_status = EXIT_KILLED; + status = pcb_queue_remove_this( waiting, victim ); + pcb_zombify( victim ); + RET(pcb) = status; + break; + + default: + // this is a really bad potential problem - we have an + // unexpected or bogus process state, but we didn't + // catch that earlier. + sprint( b256, "*** kill(): victim %d, odd state %d\n", + victim->pid, victim->state ); + PANIC( 0, b256 ); + } + + SYSCALL_EXIT( status ); +} + + +/** +** sys_sleep - put the calling process to sleep for some length of time +** +** Implements: +** uint_t sleep( uint_t ms ); +** +** Puts the calling process to sleep for 'ms' milliseconds (or just yields +** the CPU if 'ms' is 0). ** Returns the time the process spent sleeping. +*/ +SYSIMPL(sleep) { + + // sanity check + assert( pcb != NULL ); + + SYSCALL_ENTER( pcb->pid ); + + // get the desired duration + uint_t length = ARG( pcb, 1 ); + + if( length == 0 ) { + + // just yield the CPU + // sleep duration is 0 + RET(pcb) = 0; + + // back on the ready queue + schedule( pcb ); + + } else { + + // sleep for a while + pcb->wakeup = system_time + length; + + if( pcb_queue_insert(sleeping,pcb) != SUCCESS ) { + // something strange is happening + WARNING( "sleep pcb insert failed" ); + // if this is the current process, report an error + if( current == pcb ) { + RET(pcb) = -1; + } + // return without dispatching a new process + return; + } + } + + // only dispatch if the current process called us + if( pcb == current ) { + current = NULL; + dispatch(); + } +} + +/* +** PRIVATE FUNCTIONS GLOBAL VARIABLES +*/ + +/* +** The system call jump table +** +** Initialized using designated initializers to ensure the entries +** are correct even if the syscall code values should happen to change. +** This also makes it easy to add new system call entries, as their +** position in the initialization list is irrelevant. +*/ + +static void (* const syscalls[N_SYSCALLS])( pcb_t * ) = { + [ SYS_exit ] = sys_exit, + [ SYS_waitpid ] = sys_waitpid, + [ SYS_fork ] = sys_fork, + [ SYS_exec ] = sys_exec, + [ SYS_read ] = sys_read, + [ SYS_write ] = sys_write, + [ SYS_getpid ] = sys_getpid, + [ SYS_getppid ] = sys_getppid, + [ SYS_gettime ] = sys_gettime, + [ SYS_getprio ] = sys_getprio, + [ SYS_setprio ] = sys_setprio, + [ SYS_kill ] = sys_kill, + [ SYS_sleep ] = sys_sleep +}; + +/** +** Name: sys_isr +** +** System call ISR +** +** @param vector Vector number for this interrupt +** @param code Error code (0 for this interrupt) +*/ +static void sys_isr( int vector, int code ) { + + // keep the compiler happy + (void) vector; + (void) code; + + // sanity check! + assert( current != NULL ); + assert( current->context != NULL ); + + // retrieve the syscall code + int num = REG( current, eax ); + +#if TRACING_SYSCALLS + cio_printf( "** --> SYS pid %u code %u\n", current->pid, num ); +#endif + + // validate it + if( num < 0 || num >= N_SYSCALLS ) { + // bad syscall number + // could kill it, but we'll just force it to exit + num = SYS_exit; + ARG(current,1) = EXIT_BAD_SYSCALL; + } + + // call the handler + syscalls[num]( current ); + +#if TRACING_SYSCALLS + cio_printf( "** <-- SYS pid %u ret %u\n", current->pid, RET(current) ); +#endif + + // tell the PIC we're done + outb( PIC1_CMD, PIC_EOI ); +} + +/* +** PUBLIC FUNCTIONS +*/ + +/** +** Name: sys_init +** +** Syscall module initialization routine +** +** Dependencies: +** Must be called after cio_init() +*/ +void sys_init( void ) { + +#if TRACING_INIT + cio_puts( " Sys" ); +#endif + + // install the second-stage ISR + install_isr( VEC_SYSCALL, sys_isr ); +} diff --git a/kernel/user.c b/kernel/user.c new file mode 100644 index 0000000..2d32157 --- /dev/null +++ b/kernel/user.c @@ -0,0 +1,774 @@ +/** +** @file user.c +** +** @author CSCI-452 class of 20245 +** +** @brief User-level code manipulation routines +*/ + +#define KERNEL_SRC + +#include + +#include +#include +#include +#include + +/* +** PRIVATE DEFINITIONS +*/ + +/* +** PRIVATE DATA TYPES +*/ + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +/* +** Location of the "user blob" in memory. +** +** These variables are filled in by the code in startup.S using values +** passed to it from the bootstrap. +** +** These are visible so that the startup code can find them. +*/ +uint16_t user_offset; // byte offset from the segment base +uint16_t user_segment; // segment base address +uint16_t user_sectors; // number of 512-byte sectors it occupies + +header_t *user_header; // filled in by the user_init routine +prog_t *prog_table; // filled in by the user_init routine + +/* +** PRIVATE FUNCTIONS +*/ + +#if TRACING_ELF + +/* +** This is debugging support code; if not debugging the ELF +** handling code, it won't be compiled into the kernel. +*/ + +// buffer used by some of these functions +static char ebuf[16]; + +/* +** File header functions +*/ + +// interpret the file class +static const char *fh_eclass( e32_si class ) { + switch( class ) { + case ELF_CLASS_NONE: return( "None" ); break; + case ELF_CLASS_32: return( "EC32" ); break; + case ELF_CLASS_64: return( "EC64" ); break; + } + return( "????" ); +} + +// interpret the data encoding +static const char *fh_edata( e32_si data ) { + switch( data ) { + case ELF_DATA_NONE: return( "Invd" ); break; + case ELF_DATA_2LSB: return( "2CLE" ); break; + case ELF_DATA_2MSB: return( "2CBE" ); break; + } + return( "????" ); +} + +// interpret the file type +static const char *fh_htype( e32_h type ) { + switch( type ) { + case ET_NONE: return( "none" ); break; + case ET_REL: return( "rel" ); break; + case ET_EXEC: return( "exec" ); break; + case ET_DYN: return( "dyn" ); break; + case ET_CORE: return( "core" ); break; + default: + if( type >= ET_LO_OS && type <= ET_HI_OS ) + return( "OSsp" ); + else if( type >= ET_LO_CP && type <= ET_HI_CP ) + return( "CPsp" ); + } + sprint( ebuf, "0x%04x", type ); + return( (const char *) ebuf ); +} + +// interpret the machine type +static const char *fh_mtype( e32_h machine ) { + switch( machine ) { + case EM_NONE: return( "None" ); break; + case EM_386: return( "386" ); break; + case EM_ARM: return( "ARM" ); break; + case EM_X86_64: return( "AMD64" ); break; + case EM_AARCH64: return( "AARCH64" ); break; + case EM_RISCV: return( "RISC-V" ); break; + } + return( "Other" ); +} + +// dump the program header +static void dump_fhdr( elfhdr_t *hdr ) { + cio_puts( "File header: magic " ); + for( int i = EI_MAG0; i <= EI_MAG3; ++i ) + put_char_or_code( hdr->e_ident.bytes[i] ); + cio_printf( " class %s", fh_eclass(hdr->e_ident.f.class) ); + cio_printf( " enc %s", fh_edata(hdr->e_ident.f.data) ); + cio_printf( " ver %u\n", hdr->e_ident.f.version ); + cio_printf( " type %s", fh_htype(hdr->e_type) ); + cio_printf( " mach %s", fh_mtype(hdr->e_machine) ); + cio_printf( " vers %d", hdr->e_version ); + cio_printf( " entr %08x\n", hdr->e_entry ); + + cio_printf( " phoff %08x", hdr->e_phoff ); + cio_printf( " shoff %08x", hdr->e_shoff ); + cio_printf( " flags %08x", (uint32_t) hdr->e_flags ); + cio_printf( " ehsize %u\n", hdr->e_ehsize ); + cio_printf( " phentsize %u", hdr->e_phentsize ); + cio_printf( " phnum %u", hdr->e_phnum ); + cio_printf( " shentsize %u", hdr->e_shentsize ); + cio_printf( " shnum %u", hdr->e_shnum ); + cio_printf( " shstrndx %u\n", hdr->e_shstrndx ); +} + +/* +** Program header functions +*/ + +// categorize the header type +static const char *ph_type( e32_w type ) { + switch( type ) { + case PT_NULL: return( "Unused" ); break; + case PT_LOAD: return( "Load" ); break; + case PT_DYNAMIC: return( "DLI" ); break; + case PT_INTERP: return( "Interp" ); break; + case PT_NOTE: return( "Aux" ); break; + case PT_SHLIB: return( "RSVD" ); break; + case PT_PHDR: return( "PTentry" ); break; + case PT_TLS: return( "TLS" ); break; + default: + if( type >= PT_LO_OS && type <= PT_HI_OS ) + return( "OSsp" ); + else if( type >= PT_LO_CP && type <= PT_HI_CP ) + return( "CPsp" ); + } + sprint( ebuf, "0x%08x", type ); + return( (const char *) ebuf ); +} + +// report the individual flags +static void ph_flags( e32_w flags ) { + if( (flags & PF_R) != 0 ) cio_putchar( 'R' ); + if( (flags & PF_W) != 0 ) cio_putchar( 'W' ); + if( (flags & PF_E) != 0 ) cio_putchar( 'X' ); +} + +// dump a program header +static void dump_phdr( elfproghdr_t *hdr, int n ) { + cio_printf( "Prog header %d, type %s\n", n, ph_type(hdr->p_type) ); + cio_printf( " offset %08x", hdr->p_offset ); + cio_printf( " va %08x", hdr->p_va ); + cio_printf( " pa %08x\n", hdr->p_pa ); + cio_printf( " filesz %08x", hdr->p_filesz ); + cio_printf( " memsz %08x", hdr->p_memsz ); + cio_puts( " flags " ); + ph_flags( hdr->p_flags ); + cio_printf( " align %08x", hdr->p_align ); + cio_putchar( '\n' ); +} + +/* +** Section header functions +*/ + +// interpret the header type +static const char *sh_type( e32_w type ) { + switch( type ) { + case SHT_NULL: return( "Unused" ); break; + case SHT_PROGBITS: return( "Progbits" ); break; + case SHT_SYMTAB: return( "Symtab" ); break; + case SHT_STRTAB: return( "Strtab" ); break; + case SHT_RELA: return( "Rela" ); break; + case SHT_HASH: return( "Hash" ); break; + case SHT_DYNAMIC: return( "Dynamic" ); break; + case SHT_NOTE: return( "Note" ); break; + case SHT_NOBITS: return( "Nobits" ); break; + case SHT_REL: return( "Rel" ); break; + case SHT_SHLIB: return( "Shlib" ); break; + case SHT_DYNSYM: return( "Dynsym" ); break; + default: + if( type >= SHT_LO_CP && type <= SHT_HI_CP ) + return( "CCsp" ); + else if( type >= SHT_LO_US && type <= SHT_HI_US ) + return( "User" ); + } + sprint( ebuf, "0x%08x", type ); + return( (const char *) ebuf ); +} + +// report the various flags +static void sh_flags( unsigned int flags ) { + if( (flags & SHF_WRITE) != 0 ) cio_putchar( 'W' ); + if( (flags & SHF_ALLOC) != 0 ) cio_putchar( 'A' ); + if( (flags & SHF_EXECINSTR) != 0 ) cio_putchar( 'X' ); + if( (flags & SHF_MERGE) != 0 ) cio_putchar( 'M' ); + if( (flags & SHF_STRINGS) != 0 ) cio_putchar( 'S' ); + if( (flags & SHF_INFO_LINK) != 0 ) cio_putchar( 'L' ); + if( (flags & SHF_LINK_ORDER) != 0 ) cio_putchar( 'o' ); + if( (flags & SHF_OS_NONCON) != 0 ) cio_putchar( 'n' ); + if( (flags & SHF_GROUP) != 0 ) cio_putchar( 'g' ); + if( (flags & SHF_TLS) != 0 ) cio_putchar( 't' ); +} + +// dump a section header +__attribute__((__unused__)) +static void dump_shdr( elfsecthdr_t *hdr, int n ) { + cio_printf( "Sect header %d, type %d (%s), name %s\n", + n, hdr->sh_type, sh_type(hdr->sh_type) ); + cio_printf( " flags %08x ", (uint32_t) hdr->sh_flags ); + sh_flags( hdr->sh_flags ); + cio_printf( " addr %08x", hdr->sh_addr ); + cio_printf( " offset %08x", hdr->sh_offset ); + cio_printf( " size %08x\n", hdr->sh_size ); + cio_printf( " link %08x", hdr->sh_link ); + cio_printf( " info %08x", hdr->sh_info ); + cio_printf( " align %08x", hdr->sh_addralign ); + cio_printf( " entsz %08x\n", hdr->sh_entsize ); +} +#endif + +/** +** read_phdrs(addr,phoff,phentsize,phnum) +** +** Parses the ELF program headers and each segment described into memory. +** +** @param hdr Pointer to the program header +** @param pcb Pointer to the PCB (and its PDE) +** +** @return status of the attempt: +** SUCCESS everything loaded correctly +** E_LOAD_LIMIT more than N_LOADABLE PT_LOAD sections +** other status returned from vm_add() +*/ +static int read_phdrs( elfhdr_t *hdr, pcb_t *pcb ) { + + // sanity check + assert1( hdr != NULL ); + assert2( pcb != NULL ); + +#if TRACING_USER + cio_printf( "read_phdrs(%08x,%08x)\n", (uint32_t) hdr, (uint32_t) pcb ); +#endif + + // iterate through the program headers + uint_t nhdrs = hdr->e_phnum; + + // pointer to the first header table entry + elfproghdr_t *curr = (elfproghdr_t *) ((uint32_t) hdr + hdr->e_phoff); + + // process them all + int loaded = 0; + for( uint_t i = 0; i < nhdrs; ++i, ++curr ) { + +#if TRACING_ELF + dump_phdr( curr, i ); +#endif + if( curr->p_type != PT_LOAD ) { + // not loadable --> we'll skip it + continue; + } + + if( loaded >= N_LOADABLE ) { +#if TRACING_USER + cio_puts( " LIMIT\n" ); +#endif + return E_LOAD_LIMIT; + } + + // set a pointer to the bytes within the object file + char *data = (char *) (((uint32_t)hdr) + curr->p_offset); +#if TRACING_USER + cio_printf( " data @ %08x", (uint32_t) data ); +#endif + + // copy the pages into memory + int stat = vm_add( pcb->pdir, curr->p_flags & PF_W, false, + (char *) curr->p_va, curr->p_memsz, data, curr->p_filesz ); + if( stat != SUCCESS ) { + // TODO what else should we do here? check for memory leak? + return stat; + } + + // set the section table entry in the PCB + pcb->sects[loaded].length = curr->p_memsz; + pcb->sects[loaded].addr = curr->p_va; +#if TRACING_USER + cio_printf( " loaded %u @ %08x\n", + pcb->sects[loaded].length, pcb->sects[loaded].addr ); +#endif + ++loaded; + } + + return SUCCESS; +} + +/** +** Name: stack_setup +** +** Set up the stack for a new process +** +** @param pcb Pointer to the PCB for the process +** @param entry Entry point for the new process +** @param args Argument vector to be put in place +** +** @return A pointer to the context_t on the stack, or NULL +*/ +static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) { + + /* + ** First, we need to count the space we'll need for the argument + ** vector and strings. + */ + + int argbytes = 0; + int argc = 0; + + while( args[argc] != NULL ) { + int n = strlen( args[argc] ) + 1; + // can't go over one page in size + if( (argbytes + n) > SZ_PAGE ) { + // oops - ignore this and any others + break; + } + argbytes += n; + ++argc; + } + + // Round up the byte count to the next multiple of four. + argbytes = (argbytes + 3) & MOD4_MASK; + + /* + ** Allocate the arrays. We are safe using dynamic arrays here + ** because we're using the OS stack, not the user stack. + ** + ** We want the argstrings and argv arrays to contain all zeroes. + ** The C standard states, in section 6.7.8, that + ** + ** "21 If there are fewer initializers in a brace-enclosed list + ** than there are elements or members of an aggregate, or + ** fewer characters in a string literal used to initialize an + ** array of known size than there are elements in the array, + ** the remainder of the aggregate shall be initialized + ** implicitly the same as objects that have static storage + ** duration." + ** + ** Sadly, because we're using variable-sized arrays, we can't + ** rely on this, so we have to call memclr() instead. :-( In + ** truth, it doesn't really cost us much more time, but it's an + ** annoyance. + */ + + char argstrings[ argbytes ]; + char *argv[ argc + 1 ]; + + CLEAR( argstrings ); + CLEAR( argv ); + + // Next, duplicate the argument strings, and create pointers to + // each one in our argv. + char *tmp = argstrings; + for( int i = 0; i < argc; ++i ) { + int nb = strlen(args[i]) + 1; // bytes (incl. NUL) in this string + strcpy( tmp, args[i] ); // add to our buffer + argv[i] = tmp; // remember where it was + tmp += nb; // move on + } + + // trailing NULL pointer + argv[argc] = NULL; + + /* + ** The pages for the stack were cleared when they were allocated, + ** so we don't need to remember to do that. + ** + ** We reserve one longword at the bottom of the stack to hold a + ** pointer to where argv is on the stack. + ** + ** The user code was linked with a startup function that defines + ** the entry point (_start), calls main(), and then calls exit() + ** if main() returns. We need to set up the stack this way: + ** + ** esp -> context <- context save area + ** ... <- context save area + ** context <- context save area + ** entry_pt <- return address for the ISR + ** argc <- argument count for main() + ** /-> argv <- argv pointer for main() + ** | ... <- argv array w/trailing NULL + ** | ... <- argv character strings + ** \--- ptr <- last word in stack + ** + ** Stack alignment rules for the SysV ABI i386 supplement dictate that + ** the 'argc' parameter must be at an address that is a multiple of 16; + ** see below for more information. + */ + + // Pointer to the last word in stack. We get this from the + // VM hierarchy. Get the PDE entry for the user address space. + pde_t stack_pde = pcb->pdir[USER_PDE]; + + // The PDE entry points to the PT, which is an array of PTE. The last + // two entries are for the stack; pull out the last one. + pte_t stack_pte = ((pte_t *)(stack_pde & MOD4K_MASK))[USER_STK_PTE2]; + + // OK, now we have the PTE. The frame address of the last page is + // in this PTE. Find the address immediately after that. + uint32_t *ptr = (uint32_t *) + ((uint32_t)(stack_pte & MOD4K_MASK) + SZ_PAGE); + + // Pointer to where the arg strings should be filled in. + char *strings = (char *) ( (uint32_t) ptr - argbytes ); + + // back the pointer up to the nearest word boundary; because we're + // moving toward location 0, the nearest word boundary is just the + // next smaller address whose low-order two bits are zeroes + strings = (char *) ((uint32_t) strings & MOD4_MASK); + + // Copy over the argv strings. + memcpy( (void *)strings, argstrings, argbytes ); + + /* + ** Next, we need to copy over the argv pointers. Start by + ** determining where 'argc' should go. + ** + ** Stack alignment is controlled by the SysV ABI i386 supplement, + ** version 1.2 (June 23, 2016), which states in section 2.2.2: + ** + ** "The end of the input argument area shall be aligned on a 16 + ** (32 or 64, if __m256 or __m512 is passed on stack) byte boundary. + ** In other words, the value (%esp + 4) is always a multiple of 16 + ** (32 or 64) when control is transferred to the function entry + ** point. The stack pointer, %esp, always points to the end of the + ** latest allocated stack frame." + ** + ** Isn't technical documentation fun? Ultimately, this means that + ** the first parameter to main() should be on the stack at an address + ** that is a multiple of 16. + ** + ** The space needed for argc, argv, and the argv array itself is + ** argc + 3 words (argc+1 for the argv entries, plus one word each + ** for argc and argv). We back up that much from 'strings'. + */ + + int nwords = argc + 3; + uint32_t *acptr = ((uint32_t *) strings) - nwords; + + /* + ** Next, back up until we're at a multiple-of-16 address. Because we + ** are moving to a lower address, its upper 28 bits are identical to + ** the address we currently have, so we can do this with a bitwise + ** AND to just turn off the lower four bits. + */ + + acptr = (uint32_t *) ( ((uint32_t)acptr) & MOD16_MASK ); + + // copy in 'argc' + *acptr = argc; + + // next, 'argv', which follows 'argc'; 'argv' points to the + // word that follows it in the stack + uint32_t *avptr = acptr + 2; + *(acptr+1) = (uint32_t) avptr; + + /* + ** Next, we copy in all argc+1 pointers. + */ + + // Adjust and copy the string pointers. + for( int i = 0; i <= argc; ++i ) { + if( argv[i] != NULL ) { + // an actual pointer - adjust it and copy it in + *avptr = (uint32_t) strings; + // skip to the next entry in the array + strings += strlen(argv[i]) + 1; + } else { + // end of the line! + *avptr = NULL; + } + ++avptr; + } + + /* + ** Now, we need to set up the initial context for the executing + ** process. + ** + ** When this process is dispatched, the context restore code will + ** pop all the saved context information off the stack, including + ** the saved EIP, CS, and EFLAGS. We set those fields up so that + ** the interrupt "returns" to the entry point of the process. + */ + + // Locate the context save area on the stack. + context_t *ctx = ((context_t *) avptr) - 1; + + /* + ** We cleared the entire stack earlier, so all the context + ** fields currently contain zeroes. We now need to fill in + ** all the important fields. + */ + + ctx->eflags = DEFAULT_EFLAGS; // IE enabled, PPL 0 + ctx->eip = entry; // initial EIP + ctx->cs = GDT_CODE; // segment registers + ctx->ss = GDT_STACK; + ctx->ds = ctx->es = ctx->fs = ctx->gs = GDT_DATA; + + /* + ** Return the new context pointer to the caller. It will be our + ** caller's responsibility to schedule this process. + */ + + return( ctx ); +} + +/* +** PUBLIC FUNCTIONS +*/ + +/** +** Name: user_init +** +** Initializes the user support module. +*/ +void user_init( void ) { + +#if TRACING_INIT + cio_puts( " User" ); +#endif + + // This is gross, but we need to get this information somehow. + // Access the "user blob" data in the second bootstrap sector + uint16_t *blobdata = (uint16_t *) USER_BLOB_DATA; + user_offset = *blobdata++; + user_segment = *blobdata++; + user_sectors = *blobdata++; + +#if TRACING_USER + cio_printf( "\nUser blob: %u sectors @ %04x:%04x", user_sectors, + user_segment, user_offset ); +#endif + + // calculate the location of the user blob + if( user_sectors > 0 ) { + + // calculate the address of the header + user_header = (header_t *) + ( KERN_BASE + + ( (((uint_t)user_segment) << 4) + ((uint_t)user_offset) ) + ); + + // the program table immediate follows the blob header + prog_table = (prog_t *) (user_header + 1); + +#if TRACING_USER + cio_printf( ", hdr %08x, %u progs, tbl %08x\n", (uint32_t) user_header, + user_header->num, (uint32_t) prog_table ); +#endif + + } else { + // too bad, so sad! + user_header = NULL; + prog_table = NULL; +#if TRACING_USER + cio_putchar( '\n' ); +#endif + } +} + +/** +** Name: user_locate +** +** Locates a user program in the user code archive. +** +** @param what The ID of the user program to find +** +** @return pointer to the program table entry in the code archive, or NULL +*/ +prog_t *user_locate( uint_t what ) { + + // no programs if there is no blob! + if( user_header == NULL ) { + return NULL; + } + + // make sure this is a reasonable program to request + if( what >= user_header->num ) { + // no such program! + return NULL; + } + + // find the entry in the program table + prog_t *prog = &prog_table[what]; + + // if there are no bytes, it's useless + if( prog->size < 1 ) { + return NULL; + } + + // return the program table pointer + return prog; +} + +/** +** Name: user_duplicate +** +** Duplicates the memory setup for an existing process. +** +** @param new The PCB for the new copy of the program +** @param old The PCB for the existing the program +** +** @return the status of the duplicate attempt +*/ +int user_duplicate( pcb_t *new, pcb_t *old ) { + + // We need to do a recursive duplication of the process address + // space of the current process. First, we create a new user + // page directory. Next, we'll duplicate the USER_PDE page + // table. Finally, we'll go through that table and duplicate + // all the frames. + + // create the initial VM hierarchy + pde_t *pdir = vm_mkuvm(); + if( pdir == NULL ) { + return E_NO_MEMORY; + } + new->pdir = pdir; + + // next, add a USER_PDE page table that's a duplicate of the + // current process' page table + if( !vm_uvmdup(old->pdir,new->pdir) ) { + // check for memory leak? + return E_NO_MEMORY; + } + + // now, iterate through the entries, replacing the frame + // numbers with duplicate frames + // + // NOTE: we only deal with pdir[0] here, as we are limiting + // the user address space to the first 4MB + pte_t *pt = (pte_t *) (pdir[USER_PDE]); + + for( int i = 0; i < N_PTE; ++i ) { + + // if this entry is present, + if( IS_PRESENT(*pt) ) { + + // duplicate the page + void *tmp = vm_pagedup( (void *) (*pt & FRAME_MASK) ); + // replace the old frame number with the new one + *pt = (pte_t) (((uint32_t)tmp) | (*pt & PERM_MASK)); + + } else { + + *pt = 0; + + } + ++pt; + } + + return SUCCESS; +} + +/** +** Name: user_load +** +** Loads a user program from the user code archive into memory. +** Allocates all needed frames and sets up the VM tables. +** +** @param ptab A pointer to the program table entry to be loaded +** @param pcb The PCB for the program being loaded +** @param args The argument vector for the program +** +** @return the status of the load attempt +*/ +int user_load( prog_t *ptab, pcb_t *pcb, const char **args ) { + + // NULL pointers are bad! + assert1( ptab != NULL ); + assert1( pcb != NULL ); + assert1( args != NULL ); + + // locate the ELF binary + elfhdr_t *hdr = (elfhdr_t *) ((uint32_t)user_header + ptab->offset); + +#if TRACING_ELF + cio_printf( "Load: ptab %08x: '%s', off %08x, size %08x, flags %08x\n", + (uint32_t) ptab, ptab->name, ptab->offset, ptab->size, + ptab->flags ); + cio_printf( " args %08x:", (uint32_t) args ); + for( int i = 0; args[i] != NULL; ++i ) { + cio_printf( " [%d] %s", i, args[i] ); + } + cio_printf( "\n pcb %08x (pid %u)\n", (uint32_t) pcb, pcb->pid ); + dump_fhdr( hdr ); +#endif + + // verify the ELF header + if( hdr->e_ident.f.magic != ELF_MAGIC ) { + return E_BAD_PARAM; + } + + // allocate a page directory + pcb->pdir = vm_mkuvm(); + if( pcb->pdir == NULL ) { + return E_NO_MEMORY; + } + + // read all the program headers + int stat = read_phdrs( hdr, pcb ); + if( stat != SUCCESS ) { + // TODO figure out a better way to deal with this + PANIC( 0, "user_load: phdr read failed" ); + } + + // next, set up the runtime stack - just like setting up loadable + // sections, except nothing to copy + stat = vm_add( pcb->pdir, true, false, (void *) USER_STACK, + SZ_USTACK, NULL, 0 ); + if( stat != SUCCESS ) { + // TODO yadda yadda... + PANIC( 0, "user_load: vm_add failed" ); + } + + // set up the command-line arguments + pcb->context = stack_setup( pcb, hdr->e_entry, args ); + + return SUCCESS; +} + +/** +** Name: user_cleanup +** +** "Unloads" a user program. Deallocates all memory frames and +** cleans up the VM structures. +** +** @param pcb The PCB of the program to be unloaded +*/ +void user_cleanup( pcb_t *pcb ) { + + if( pcb == NULL ) { + // should this be an error? + return; + } + + vm_free( pcb->pdir ); + pcb->pdir = NULL; +} diff --git a/kernel/vm.c b/kernel/vm.c new file mode 100644 index 0000000..46c4eab --- /dev/null +++ b/kernel/vm.c @@ -0,0 +1,585 @@ +/** +** @file vm.c +** +** @author CSCI-452 class of 20245 +** +** @brief Kernel VM support +*/ + +#define KERNEL_SRC + +#include + +#include +#include + +#include +#include +#include +#include + +/* +** PRIVATE DEFINITIONS +*/ + +/* +** PRIVATE DATA TYPES +*/ + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +// created page directory for the kernel +pde_t *kpdir; + +/* +** PRIVATE FUNCTIONS +*/ + +/** +** Name: vm_isr +** +** Description: Page fault handler +** +** @param vector Interrupt vector number +** @param code Error code pushed onto the stack +*/ +static void vm_isr( int vector, int code ) { + + // get whatever information we can from the fault + pfec_t fault; + fault.u = (uint32_t) code; + uint32_t addr = r_cr2(); + + // report what we found + sprint( b256, + "** page fault @ 0x%08x %cP %c %cM %cRSV %c %cPK %cSS %cHLAT %cSGZ", + addr, + fault.s.p ? ' ' : '!', + fault.s.w ? 'W' : 'R', + fault.s.us ? 'U' : 'S', + fault.s.rsvd ? ' ' : '!', + fault.s.id ? 'I' : 'D', + fault.s.pk ? ' ' : '!', + fault.s.ss ? ' ' : '!', + fault.s.hlat ? ' ' : '!', + fault.s.sgz ? ' ' : '!' + ); + + // and give up + PANIC( 0, b256 ); +} + +/** +** Name: uva2kva +** +** Convert a user VA into a kernel address +*/ +__attribute__((__unused__)) +static void *uva2kva( pde_t *pdir, void *va ) { + + // find the PMT entry for this address + pte_t *pte = vm_getpte( pdir, va, false ); + if( pte == NULL ) { + return NULL; + } + + // is this a valid address for the user? + if( IS_PRESENT(*pte) ) { + return 0; + } + + if( IS_LARGE(*pte) ) { + return 0; + } + + // get the physical address + uint32_t frame = *pte & FRAME_MASK; // keep the frame address + frame |= ((uint32_t) va) & PERM_MASK; // OR in the lower 12 bits + + return (void *) frame; +} + + +/* +** PUBLIC FUNCTIONS +*/ + +/** +** Name: vm_init +** +** Description: Initialize the VM module +*/ +void vm_init( void ) { + +#if TRACING_INIT + cio_puts( " VM" ); +#endif + + // set up the kernel's page directory + kpdir = vm_mkkvm(); + assert( kpdir != NULL ); + + // install the page fault handler + install_isr( VEC_PAGE_FAULT, vm_isr ); +} + +/** +** Name: vm_pagedup +** +** Duplicate a page of memory +** +** @param old Pointer to the first byte of a page +** +** @return a pointer to the new, duplicate page, or NULL +*/ +void *vm_pagedup( void *old ) { + void *new = (void *) km_page_alloc(); + if( new != NULL ) { + memcpy( new, old, SZ_PAGE ); + } + return new; +} + +/** +** Name: vm_ptdup +** +** Duplicate a page directory entry +** +** @param dst Pointer to where the duplicate should go +** @param curr Pointer to the entry to be duplicated +** +** @return true on success, else false +*/ +bool_t vm_ptdup( pde_t *dst, pde_t *curr ) { + +#if TRACING_VM + cio_printf( "vm_ptdup dst %08x curr %08x\n", + (uint32_t) dst, (uint32_t) curr ); +#endif + // simplest case + if( *curr == 0 ) { + *dst = 0; + return true; + } + + // OK, we have an entry; allocate a page table + pte_t *pt = (pte_t *) km_page_alloc(); + if( pt == NULL ) { + return false; + } + + // pointer to the first PTE in the current table + pte_t *old = (pte_t *) (((uint32_t) *curr) & FRAME_MASK); + // pointer to the first PTE in the new table + pte_t *new = pt; + + for( int i = 0 ; i < N_PTE; ++i ) { + if( IS_PRESENT(*old) ) { + *new = 0; + } else { + *new = *old; + } + ++old; + ++new; + } + + // assign the page table into the new page directory + // upper 22 bits from 'pt', lower 12 from '*curr' + *dst = (pde_t) ( + (((uint32_t)pt) & FRAME_MASK) | + (((uint32_t)(*curr)) & PERM_MASK ) + ); + + return true; +} + +/** +** Name: vm_getpte +** +** Return the address of the PTE corresponding to the virtual address +** 'va' within the address space controlled by 'pgdir'. If there is no +** page table for that VA and 'alloc' is true, create the necessary +** page table entries. +** +** @param pdir Pointer to the page directory to be searched +** @param va The virtual address we're looking for +** @param alloc Should we allocate a page table if there isn't one? +** +** @return A pointer to the page table entry for this VA, or NULL +*/ +pte_t *vm_getpte( pde_t *pdir, const void *va, bool_t alloc ) { + pte_t *ptab; + + // sanity check + assert1( pdir != NULL ); + + // get the PDIR entry for this virtual address + pde_t *pde = &pdir[ PDIX(va) ]; + + // is it already set up? + if( IS_PRESENT(*pde) ) { + + // yes! + ptab = (pte_t*)P2V(PTE_ADDR(*pde)); + + } else { + + // no - should we create it? + if( !alloc ) { + // nope, so just return + return NULL; + } + + // yes - try to allocate a page table + ptab = (pte_t *) km_page_alloc(); + if( ptab == NULL ) { + WARNING( "can't allocate page table" ); + return NULL; + } + + // who knows what was left in this page.... + memclr( ptab, SZ_PAGE ); + + // add this to the page directory + // + // we set this up to allow general access; this could be + // controlled by setting access control in the page table + // entries, if necessary. + *pde = V2P(ptab) | PDE_P | PDE_RW; + } + + // finally, return a pointer to the entry in the + // page table for this VA + return &ptab[ PTIX(va) ]; +} + +// Set up kernel part of a page table. +pde_t *vm_mkkvm( void ) +{ + mapping_t *k; + + // allocate the page directory + pde_t *pdir = km_page_alloc(); + if( pdir == NULL ) { + return NULL; + } + + // clear it out to disable all the entries + memclr( pdir, SZ_PAGE ); + + // map in all the page ranges + k = kmap; + for( int i = 0; i < n_kmap; ++i, ++k ) { + int stat = vm_map( pdir, ((void *)k->va_start), + k->pa_end - k->pa_start, + k->pa_start, k->perm ); + if( stat != SUCCESS ) { + vm_free( pdir ); + return 0; + } + } + + return pdir; +} + +/* +** Creates an initial user VM table hierarchy by copying the +** system entries into a new page directory. +** +** @return a pointer to the new page directory, or NULL +*/ +pde_t *vm_mkuvm( void ) { + + // allocate the directory + pde_t *new = (pde_t *) km_page_alloc(); + if( new == NULL ) { + return NULL; + } + + // iterate through the kernel page directory + pde_t *curr = kpdir; + pde_t *dst = new; + for( int i = 0; i < N_PDE; ++i ) { + + if( *curr != 0 ) { + // found an active one - duplicate it + if( !vm_ptdup(dst,curr) ) { + return NULL; + } + } + + ++curr; + ++dst; + } + + return new; + +} + +/** +** Name: vm_set_kvm +** +** Switch the page table register to the kernel's page directory. +*/ +void vm_set_kvm( void ) { + w_cr3( V2P(kpdir) ); // switch to the kernel page table +} + +/** +** Name: vm_set_uvm +** +** Switch the page table register to the page directory for a user process. +** +** @param p PCB of the process we're switching to +*/ +void vm_set_uvm( pcb_t *p ) { + assert( p != NULL ); + assert( p->pdir != NULL ); + + w_cr3( V2P(p->pdir) ); // switch to process's address space +} + +/** +** Name: vm_add +** +** Add pages to the page hierarchy for a process, copying data into +** them if necessary. +** +** @param pdir Pointer to the page directory to modify +** @param wr "Writable" flag for the PTE +** @param sys "System" flag for the PTE +** @param va Starting VA of the range +** @param size Amount of physical memory to allocate (bytes) +** @param data Pointer to data to copy, or NULL +** @param bytes Number of bytes to copy +** +** @return status of the allocation attempt +*/ +int vm_add( pde_t *pdir, bool_t wr, bool_t sys, + void *va, uint32_t size, char *data, uint32_t bytes ) { + + // how many pages do we need? + uint_t npages = ((size & MOD4K_BITS) ? PGUP(size) : size) >> MOD4K_SHIFT; + + // permission set for the PTEs + uint_t entrybase = PTE_P; + if( wr ) { + entrybase |= PTE_RW; + } + if( sys ) { + entrybase |= PTE_US; + } + +#if TRACING_VM + cio_printf( "vm_add: pdir %08x, %s, va %08x (%u, %u pgs)\n", + (uint32_t) pdir, wr ? "W" : "!W", (uint32_t) va, size ); + cio_printf( " from %08x, %u bytes, perms %08x\n", + (uint32_t) data, bytes, entrybase ); +#endif + + // iterate through the pages + + for( int i = 0; i < npages; ++i ) { + + // figure out where this page will go in the hierarchy + pte_t *pte = vm_getpte( pdir, va, true ); + if( pte == NULL ) { + // TODO if i > 0, this isn't the first frame - is + // there anything to do about other frames? + // POSSIBLE MEMORY LEAK? + return E_NO_MEMORY; + } + + // allocate the frame + void *page = km_page_alloc(); + if( page == NULL ) { + // TODO same question here + return E_NO_MEMORY; + } + + // clear it all out + memclr( page, SZ_PAGE ); + + // create the PTE for this frame + uint32_t entry = (uint32_t) (PTE_ADDR(page) | entrybase); + *pte = entry; + + // copy data if we need to + if( data != NULL && bytes > 0 ) { + // how much to copy + uint_t num = bytes > SZ_PAGE ? SZ_PAGE : bytes; + // do it! + memcpy( (void *)page, (void *)data, num ); + // adjust all the pointers + data += num; // where to continue + bytes -= num; // what's left to copy + } + + // bump the virtual address + va += SZ_PAGE; + } + + return SUCCESS; + +} + +/** +** Name: vm_free +** +** Deallocate a page table hierarchy and all physical memory frames +** in the user portion. +** +** @param pdir Pointer to the page directory +*/ +void vm_free( pde_t *pdir ) { + + // do we have anything to do? + if( pdir == NULL ) { + return; + } + + // iterate through the page directory entries, freeing the + // PMTS and the frames they point to + pde_t *curr = pdir; + for( int i = 0; i < N_PDE; ++i ) { + + // does this entry point to anything useful? + if( IS_PRESENT(*curr) ) { + + // yes - get the PMT pointer + pte_t *pte = (pte_t *) PTE_ADDR(*curr); + + // walk the PMT + for( int j = 0; j < N_PTE; ++j ) { + // does this entry point to a frame? + if( IS_PRESENT(*pte) ) { + // yes - free the frame + km_page_free( (void *) PTE_ADDR(*pte) ); + // mark it so we don't get surprised + *pte = 0; + } + // move on + ++pte; + } + // now, free the PMT itself + km_page_free( (void *) PDE_ADDR(*curr) ); + *curr = 0; + } + + // move to the next entry + ++curr; + } + + // finally, free the PDIR itself + km_page_free( (void *) pdir ); +} + +/* +** Name: vm_map +** +** Create PTEs for virtual addresses starting at 'va' that refer to +** physical addresses in the range [pa, pa+size-1]. We aren't guaranteed +** that va is page-aligned. +** +** @param pdir Page directory for this address space +** @param va The starting virtual address +** @param size Length of the range to be mapped +** @param pa The starting physical address +** @param perm Permission bits for the PTEs +*/ +int vm_map( pde_t *pdir, void *va, uint_t size, uint_t pa, int perm ) { + pte_t *pte; + + // round the VA down to its page boundary + char *addr = (char*)PGDOWN((uint_t)va); + + // round the end of the range down to its page boundary + char *last = (char*)PGDOWN(((uint_t)va) + size - 1); + + for(;;) { + + // get a pointer to the PTE for the current VA + if( (pte = vm_getpte(pdir, addr, 1)) == 0 ) { + // couldn't find it + return E_NO_PTE; + } + + // if this entry has already been mapped, we're in trouble + if( IS_PRESENT(*pte) ) { + PANIC( 0, "mapping an already-mapped address" ); + } + + // ok, set the PTE as requested + *pte = pa | perm | PTE_P; + + // are we done? + if( addr == last ) { + break; + } + + // nope - move to the next page + addr += SZ_PAGE; + pa += SZ_PAGE; + } + return 0; +} + +/** +** Name: vm_uvmdup +** +** Create a duplicate of the user portio of an existing page table +** hierarchy. We assume that the "new" page directory exists and +** the system portions of it should not be touched. +** +** Note: we do not duplicate the frames in the hierarchy - we just +** create a duplicate of the hierarchy itself. This means that we +** now have two sets of page tables that refer to the same user-level +** frames in memory. +** +** @param old Existing page directory +** @param new New page directory +** +** @return status of the duplication attempt +*/ +int vm_uvmdup( pde_t *old, pde_t *new ) { + + if( old == NULL || new == NULL ) { + return E_BAD_PARAM; + } + + // we only want to deal with the "user" half of the address space + for( int i = 0; i < (N_PDE >> 1); ++i ) { + + // is this entry in use? + if( IS_PRESENT(*old) ) { + + // yes. if it points to a 4MB page, we just copy it; + // otherwise, we must duplicate the next level PMT + + *new = *old; // copy the entry + + if( !IS_LARGE(*old) ) { + + // it's a 4KB page, so we need to duplicate the PMT + pte_t *newpmt = (pte_t *) vm_pagedup( (void *) (*old & FRAME_MASK) ); + if( newpmt == NULL ) { + return E_NO_MEMORY; + } + + // create the new PDE entry by replacing the frame # + *new = (pde_t) (((uint32_t)newpmt) | PERMS(*old)); + } + } + + ++old; + ++new; + } + + return SUCCESS; +} diff --git a/kernel/vmtables.c b/kernel/vmtables.c new file mode 100644 index 0000000..306b1f6 --- /dev/null +++ b/kernel/vmtables.c @@ -0,0 +1,270 @@ +/** +** @file vmtables.c +** +** @author CSCI-452 class of 20245 +** +** @brief Kernel VM tables +** +** Compilation options: +** +** MAKE_IDENTITY_MAP Creates a page table that identity-maps the first +** 4MB of main memory. +*/ + +#define KERNEL_SRC + +#include + +#include +#include +#include +#include + +// defined for us by the linker +extern char _data[]; + +/* +** Initial page directory, for when the kernel is starting up +** +** we use large (4MB) pages here to allow us to use a one-level +** paging hierarchy; the kernel will create a new page table +** hierarchy once memory is initialized +** +** We only map the first 2GB of memory, plus a 4MB portion of +** the upper half, which we map to cover the first 4MB of +** memory. +*/ + +// identity-map 4MB page #n +#define L(n) [n] = (pde_t) ( (TO_4MFRAME((n))) | (PDE_P|PDE_RW|PDE_PS) ) + +ALIGN(SZ_PAGE) +pde_t firstpdir[N_PDE] = { + + // Map VA range [0, 2GB] to PA range [0, 2GB] +L(0x000), L(0x001), L(0x002), L(0x003), L(0x004), L(0x005), L(0x006), L(0x007), +L(0x008), L(0x009), L(0x00a), L(0x00b), L(0x00c), L(0x00d), L(0x00e), L(0x00f), +L(0x010), L(0x011), L(0x012), L(0x013), L(0x014), L(0x015), L(0x016), L(0x017), +L(0x018), L(0x019), L(0x01a), L(0x01b), L(0x01c), L(0x01d), L(0x01e), L(0x01f), +L(0x020), L(0x021), L(0x022), L(0x023), L(0x024), L(0x025), L(0x026), L(0x027), +L(0x028), L(0x029), L(0x02a), L(0x02b), L(0x02c), L(0x02d), L(0x02e), L(0x02f), +L(0x030), L(0x031), L(0x032), L(0x033), L(0x034), L(0x035), L(0x036), L(0x037), +L(0x038), L(0x039), L(0x03a), L(0x03b), L(0x03c), L(0x03d), L(0x03e), L(0x03f), +L(0x040), L(0x041), L(0x042), L(0x043), L(0x044), L(0x045), L(0x046), L(0x047), +L(0x048), L(0x049), L(0x04a), L(0x04b), L(0x04c), L(0x04d), L(0x04e), L(0x04f), +L(0x050), L(0x051), L(0x052), L(0x053), L(0x054), L(0x055), L(0x056), L(0x057), +L(0x058), L(0x059), L(0x05a), L(0x05b), L(0x05c), L(0x05d), L(0x05e), L(0x05f), +L(0x060), L(0x061), L(0x062), L(0x063), L(0x064), L(0x065), L(0x066), L(0x067), +L(0x068), L(0x069), L(0x06a), L(0x06b), L(0x06c), L(0x06d), L(0x06e), L(0x06f), +L(0x070), L(0x071), L(0x072), L(0x073), L(0x074), L(0x075), L(0x076), L(0x077), +L(0x078), L(0x079), L(0x07a), L(0x07b), L(0x07c), L(0x07d), L(0x07e), L(0x07f), +L(0x080), L(0x081), L(0x082), L(0x083), L(0x084), L(0x085), L(0x086), L(0x087), +L(0x088), L(0x089), L(0x08a), L(0x08b), L(0x08c), L(0x08d), L(0x08e), L(0x08f), +L(0x090), L(0x091), L(0x092), L(0x093), L(0x094), L(0x095), L(0x096), L(0x097), +L(0x098), L(0x099), L(0x09a), L(0x09b), L(0x09c), L(0x09d), L(0x09e), L(0x09f), +L(0x0a0), L(0x0a1), L(0x0a2), L(0x0a3), L(0x0a4), L(0x0a5), L(0x0a6), L(0x0a7), +L(0x0a8), L(0x0a9), L(0x0aa), L(0x0ab), L(0x0ac), L(0x0ad), L(0x0ae), L(0x0af), +L(0x0b0), L(0x0b1), L(0x0b2), L(0x0b3), L(0x0b4), L(0x0b5), L(0x0b6), L(0x0b7), +L(0x0b8), L(0x0b9), L(0x0ba), L(0x0bb), L(0x0bc), L(0x0bd), L(0x0be), L(0x0bf), +L(0x0c0), L(0x0c1), L(0x0c2), L(0x0c3), L(0x0c4), L(0x0c5), L(0x0c6), L(0x0c7), +L(0x0c8), L(0x0c9), L(0x0ca), L(0x0cb), L(0x0cc), L(0x0cd), L(0x0ce), L(0x0cf), +L(0x0d0), L(0x0d1), L(0x0d2), L(0x0d3), L(0x0d4), L(0x0d5), L(0x0d6), L(0x0d7), +L(0x0d8), L(0x0d9), L(0x0da), L(0x0db), L(0x0dc), L(0x0dd), L(0x0de), L(0x0df), +L(0x0e0), L(0x0e1), L(0x0e2), L(0x0e3), L(0x0e4), L(0x0e5), L(0x0e6), L(0x0e7), +L(0x0e8), L(0x0e9), L(0x0ea), L(0x0eb), L(0x0ec), L(0x0ed), L(0x0ee), L(0x0ef), +L(0x0f0), L(0x0f1), L(0x0f2), L(0x0f3), L(0x0f4), L(0x0f5), L(0x0f6), L(0x0f7), +L(0x0f8), L(0x0f9), L(0x0fa), L(0x0fb), L(0x0fc), L(0x0fd), L(0x0fe), L(0x0ff), +L(0x100), L(0x101), L(0x102), L(0x103), L(0x104), L(0x105), L(0x106), L(0x107), +L(0x108), L(0x109), L(0x10a), L(0x10b), L(0x10c), L(0x10d), L(0x10e), L(0x10f), +L(0x110), L(0x111), L(0x112), L(0x113), L(0x114), L(0x115), L(0x116), L(0x117), +L(0x118), L(0x119), L(0x11a), L(0x11b), L(0x11c), L(0x11d), L(0x11e), L(0x11f), +L(0x120), L(0x121), L(0x122), L(0x123), L(0x124), L(0x125), L(0x126), L(0x127), +L(0x128), L(0x129), L(0x12a), L(0x12b), L(0x12c), L(0x12d), L(0x12e), L(0x12f), +L(0x130), L(0x131), L(0x132), L(0x133), L(0x134), L(0x135), L(0x136), L(0x137), +L(0x138), L(0x139), L(0x13a), L(0x13b), L(0x13c), L(0x13d), L(0x13e), L(0x13f), +L(0x140), L(0x141), L(0x142), L(0x143), L(0x144), L(0x145), L(0x146), L(0x147), +L(0x148), L(0x149), L(0x14a), L(0x14b), L(0x14c), L(0x14d), L(0x14e), L(0x14f), +L(0x150), L(0x151), L(0x152), L(0x153), L(0x154), L(0x155), L(0x156), L(0x157), +L(0x158), L(0x159), L(0x15a), L(0x15b), L(0x15c), L(0x15d), L(0x15e), L(0x15f), +L(0x160), L(0x161), L(0x162), L(0x163), L(0x164), L(0x165), L(0x166), L(0x167), +L(0x168), L(0x169), L(0x16a), L(0x16b), L(0x16c), L(0x16d), L(0x16e), L(0x16f), +L(0x170), L(0x171), L(0x172), L(0x173), L(0x174), L(0x175), L(0x176), L(0x177), +L(0x178), L(0x179), L(0x17a), L(0x17b), L(0x17c), L(0x17d), L(0x17e), L(0x17f), +L(0x180), L(0x181), L(0x182), L(0x183), L(0x184), L(0x185), L(0x186), L(0x187), +L(0x188), L(0x189), L(0x18a), L(0x18b), L(0x18c), L(0x18d), L(0x18e), L(0x18f), +L(0x190), L(0x191), L(0x192), L(0x193), L(0x194), L(0x195), L(0x196), L(0x197), +L(0x198), L(0x199), L(0x19a), L(0x19b), L(0x19c), L(0x19d), L(0x19e), L(0x19f), +L(0x1a0), L(0x1a1), L(0x1a2), L(0x1a3), L(0x1a4), L(0x1a5), L(0x1a6), L(0x1a7), +L(0x1a8), L(0x1a9), L(0x1aa), L(0x1ab), L(0x1ac), L(0x1ad), L(0x1ae), L(0x1af), +L(0x1b0), L(0x1b1), L(0x1b2), L(0x1b3), L(0x1b4), L(0x1b5), L(0x1b6), L(0x1b7), +L(0x1b8), L(0x1b9), L(0x1ba), L(0x1bb), L(0x1bc), L(0x1bd), L(0x1be), L(0x1bf), +L(0x1c0), L(0x1c1), L(0x1c2), L(0x1c3), L(0x1c4), L(0x1c5), L(0x1c6), L(0x1c7), +L(0x1c8), L(0x1c9), L(0x1ca), L(0x1cb), L(0x1cc), L(0x1cd), L(0x1ce), L(0x1cf), +L(0x1d0), L(0x1d1), L(0x1d2), L(0x1d3), L(0x1d4), L(0x1d5), L(0x1d6), L(0x1d7), +L(0x1d8), L(0x1d9), L(0x1da), L(0x1db), L(0x1dc), L(0x1dd), L(0x1de), L(0x1df), +L(0x1e0), L(0x1e1), L(0x1e2), L(0x1e3), L(0x1e4), L(0x1e5), L(0x1e6), L(0x1e7), +L(0x1e8), L(0x1e9), L(0x1ea), L(0x1eb), L(0x1ec), L(0x1ed), L(0x1ee), L(0x1ef), +L(0x1f0), L(0x1f1), L(0x1f2), L(0x1f3), L(0x1f4), L(0x1f5), L(0x1f6), L(0x1f7), +L(0x1f8), L(0x1f9), L(0x1fa), L(0x1fb), L(0x1fc), L(0x1fd), L(0x1fe), L(0x1ff), + + // Map VA range [KERN_BASE, KERN_BASE+4MB] to PA range [0, 4MB] + [PDIX(KERN_BASE)] = (pde_t) (PDE_P | PDE_RW | PDE_PS) +}; + +#ifdef MAKE_IDENTITY_MAP +/* +** "Identity" page map table. +** +** This just maps the first 4MB of physical memory. It is initialized +** in vm_init(). +** +** This could be converted into a 4GB map of 4MB pages by turning on +** the PDE_PS bit in each entry. +*/ + +// identity-map 4KB page #n +#define S(n) [n] = (pte_t) ( (TO_4KFRAME((n))) | (PTE_P|PTE_RW) ) + +pte_t id_map[N_PTE] = { +S(0x000), S(0x001), S(0x002), S(0x003), S(0x004), S(0x005), S(0x006), S(0x007), +S(0x008), S(0x009), S(0x00a), S(0x00b), S(0x00c), S(0x00d), S(0x00e), S(0x00f), +S(0x010), S(0x011), S(0x012), S(0x013), S(0x014), S(0x015), S(0x016), S(0x017), +S(0x018), S(0x019), S(0x01a), S(0x01b), S(0x01c), S(0x01d), S(0x01e), S(0x01f), +S(0x020), S(0x021), S(0x022), S(0x023), S(0x024), S(0x025), S(0x026), S(0x027), +S(0x028), S(0x029), S(0x02a), S(0x02b), S(0x02c), S(0x02d), S(0x02e), S(0x02f), +S(0x030), S(0x031), S(0x032), S(0x033), S(0x034), S(0x035), S(0x036), S(0x037), +S(0x038), S(0x039), S(0x03a), S(0x03b), S(0x03c), S(0x03d), S(0x03e), S(0x03f), +S(0x040), S(0x041), S(0x042), S(0x043), S(0x044), S(0x045), S(0x046), S(0x047), +S(0x048), S(0x049), S(0x04a), S(0x04b), S(0x04c), S(0x04d), S(0x04e), S(0x04f), +S(0x050), S(0x051), S(0x052), S(0x053), S(0x054), S(0x055), S(0x056), S(0x057), +S(0x058), S(0x059), S(0x05a), S(0x05b), S(0x05c), S(0x05d), S(0x05e), S(0x05f), +S(0x060), S(0x061), S(0x062), S(0x063), S(0x064), S(0x065), S(0x066), S(0x067), +S(0x068), S(0x069), S(0x06a), S(0x06b), S(0x06c), S(0x06d), S(0x06e), S(0x06f), +S(0x070), S(0x071), S(0x072), S(0x073), S(0x074), S(0x075), S(0x076), S(0x077), +S(0x078), S(0x079), S(0x07a), S(0x07b), S(0x07c), S(0x07d), S(0x07e), S(0x07f), +S(0x080), S(0x081), S(0x082), S(0x083), S(0x084), S(0x085), S(0x086), S(0x087), +S(0x088), S(0x089), S(0x08a), S(0x08b), S(0x08c), S(0x08d), S(0x08e), S(0x08f), +S(0x090), S(0x091), S(0x092), S(0x093), S(0x094), S(0x095), S(0x096), S(0x097), +S(0x098), S(0x099), S(0x09a), S(0x09b), S(0x09c), S(0x09d), S(0x09e), S(0x09f), +S(0x0a0), S(0x0a1), S(0x0a2), S(0x0a3), S(0x0a4), S(0x0a5), S(0x0a6), S(0x0a7), +S(0x0a8), S(0x0a9), S(0x0aa), S(0x0ab), S(0x0ac), S(0x0ad), S(0x0ae), S(0x0af), +S(0x0b0), S(0x0b1), S(0x0b2), S(0x0b3), S(0x0b4), S(0x0b5), S(0x0b6), S(0x0b7), +S(0x0b8), S(0x0b9), S(0x0ba), S(0x0bb), S(0x0bc), S(0x0bd), S(0x0be), S(0x0bf), +S(0x0c0), S(0x0c1), S(0x0c2), S(0x0c3), S(0x0c4), S(0x0c5), S(0x0c6), S(0x0c7), +S(0x0c8), S(0x0c9), S(0x0ca), S(0x0cb), S(0x0cc), S(0x0cd), S(0x0ce), S(0x0cf), +S(0x0d0), S(0x0d1), S(0x0d2), S(0x0d3), S(0x0d4), S(0x0d5), S(0x0d6), S(0x0d7), +S(0x0d8), S(0x0d9), S(0x0da), S(0x0db), S(0x0dc), S(0x0dd), S(0x0de), S(0x0df), +S(0x0e0), S(0x0e1), S(0x0e2), S(0x0e3), S(0x0e4), S(0x0e5), S(0x0e6), S(0x0e7), +S(0x0e8), S(0x0e9), S(0x0ea), S(0x0eb), S(0x0ec), S(0x0ed), S(0x0ee), S(0x0ef), +S(0x0f0), S(0x0f1), S(0x0f2), S(0x0f3), S(0x0f4), S(0x0f5), S(0x0f6), S(0x0f7), +S(0x0f8), S(0x0f9), S(0x0fa), S(0x0fb), S(0x0fc), S(0x0fd), S(0x0fe), S(0x0ff), +S(0x100), S(0x101), S(0x102), S(0x103), S(0x104), S(0x105), S(0x106), S(0x107), +S(0x108), S(0x109), S(0x10a), S(0x10b), S(0x10c), S(0x10d), S(0x10e), S(0x10f), +S(0x110), S(0x111), S(0x112), S(0x113), S(0x114), S(0x115), S(0x116), S(0x117), +S(0x118), S(0x119), S(0x11a), S(0x11b), S(0x11c), S(0x11d), S(0x11e), S(0x11f), +S(0x120), S(0x121), S(0x122), S(0x123), S(0x124), S(0x125), S(0x126), S(0x127), +S(0x128), S(0x129), S(0x12a), S(0x12b), S(0x12c), S(0x12d), S(0x12e), S(0x12f), +S(0x130), S(0x131), S(0x132), S(0x133), S(0x134), S(0x135), S(0x136), S(0x137), +S(0x138), S(0x139), S(0x13a), S(0x13b), S(0x13c), S(0x13d), S(0x13e), S(0x13f), +S(0x140), S(0x141), S(0x142), S(0x143), S(0x144), S(0x145), S(0x146), S(0x147), +S(0x148), S(0x149), S(0x14a), S(0x14b), S(0x14c), S(0x14d), S(0x14e), S(0x14f), +S(0x150), S(0x151), S(0x152), S(0x153), S(0x154), S(0x155), S(0x156), S(0x157), +S(0x158), S(0x159), S(0x15a), S(0x15b), S(0x15c), S(0x15d), S(0x15e), S(0x15f), +S(0x160), S(0x161), S(0x162), S(0x163), S(0x164), S(0x165), S(0x166), S(0x167), +S(0x168), S(0x169), S(0x16a), S(0x16b), S(0x16c), S(0x16d), S(0x16e), S(0x16f), +S(0x170), S(0x171), S(0x172), S(0x173), S(0x174), S(0x175), S(0x176), S(0x177), +S(0x178), S(0x179), S(0x17a), S(0x17b), S(0x17c), S(0x17d), S(0x17e), S(0x17f), +S(0x180), S(0x181), S(0x182), S(0x183), S(0x184), S(0x185), S(0x186), S(0x187), +S(0x188), S(0x189), S(0x18a), S(0x18b), S(0x18c), S(0x18d), S(0x18e), S(0x18f), +S(0x190), S(0x191), S(0x192), S(0x193), S(0x194), S(0x195), S(0x196), S(0x197), +S(0x198), S(0x199), S(0x19a), S(0x19b), S(0x19c), S(0x19d), S(0x19e), S(0x19f), +S(0x1a0), S(0x1a1), S(0x1a2), S(0x1a3), S(0x1a4), S(0x1a5), S(0x1a6), S(0x1a7), +S(0x1a8), S(0x1a9), S(0x1aa), S(0x1ab), S(0x1ac), S(0x1ad), S(0x1ae), S(0x1af), +S(0x1b0), S(0x1b1), S(0x1b2), S(0x1b3), S(0x1b4), S(0x1b5), S(0x1b6), S(0x1b7), +S(0x1b8), S(0x1b9), S(0x1ba), S(0x1bb), S(0x1bc), S(0x1bd), S(0x1be), S(0x1bf), +S(0x1c0), S(0x1c1), S(0x1c2), S(0x1c3), S(0x1c4), S(0x1c5), S(0x1c6), S(0x1c7), +S(0x1c8), S(0x1c9), S(0x1ca), S(0x1cb), S(0x1cc), S(0x1cd), S(0x1ce), S(0x1cf), +S(0x1d0), S(0x1d1), S(0x1d2), S(0x1d3), S(0x1d4), S(0x1d5), S(0x1d6), S(0x1d7), +S(0x1d8), S(0x1d9), S(0x1da), S(0x1db), S(0x1dc), S(0x1dd), S(0x1de), S(0x1df), +S(0x1e0), S(0x1e1), S(0x1e2), S(0x1e3), S(0x1e4), S(0x1e5), S(0x1e6), S(0x1e7), +S(0x1e8), S(0x1e9), S(0x1ea), S(0x1eb), S(0x1ec), S(0x1ed), S(0x1ee), S(0x1ef), +S(0x1f0), S(0x1f1), S(0x1f2), S(0x1f3), S(0x1f4), S(0x1f5), S(0x1f6), S(0x1f7), +S(0x1f8), S(0x1f9), S(0x1fa), S(0x1fb), S(0x1fc), S(0x1fd), S(0x1fe), S(0x1ff), +S(0x200), S(0x201), S(0x202), S(0x203), S(0x204), S(0x205), S(0x206), S(0x207), +S(0x208), S(0x209), S(0x20a), S(0x20b), S(0x20c), S(0x20d), S(0x20e), S(0x20f), +S(0x210), S(0x211), S(0x212), S(0x213), S(0x214), S(0x215), S(0x216), S(0x217), +S(0x218), S(0x219), S(0x21a), S(0x21b), S(0x21c), S(0x21d), S(0x21e), S(0x21f), +S(0x220), S(0x221), S(0x222), S(0x223), S(0x224), S(0x225), S(0x226), S(0x227), +S(0x228), S(0x229), S(0x22a), S(0x22b), S(0x22c), S(0x22d), S(0x22e), S(0x22f), +S(0x230), S(0x231), S(0x232), S(0x233), S(0x234), S(0x235), S(0x236), S(0x237), +S(0x238), S(0x239), S(0x23a), S(0x23b), S(0x23c), S(0x23d), S(0x23e), S(0x23f), +S(0x240), S(0x241), S(0x242), S(0x243), S(0x244), S(0x245), S(0x246), S(0x247), +S(0x248), S(0x249), S(0x24a), S(0x24b), S(0x24c), S(0x24d), S(0x24e), S(0x24f), +S(0x250), S(0x251), S(0x252), S(0x253), S(0x254), S(0x255), S(0x256), S(0x257), +S(0x258), S(0x259), S(0x25a), S(0x25b), S(0x25c), S(0x25d), S(0x25e), S(0x25f), +S(0x260), S(0x261), S(0x262), S(0x263), S(0x264), S(0x265), S(0x266), S(0x267), +S(0x268), S(0x269), S(0x26a), S(0x26b), S(0x26c), S(0x26d), S(0x26e), S(0x26f), +S(0x270), S(0x271), S(0x272), S(0x273), S(0x274), S(0x275), S(0x276), S(0x277), +S(0x278), S(0x279), S(0x27a), S(0x27b), S(0x27c), S(0x27d), S(0x27e), S(0x27f), +S(0x280), S(0x281), S(0x282), S(0x283), S(0x284), S(0x285), S(0x286), S(0x287), +S(0x288), S(0x289), S(0x28a), S(0x28b), S(0x28c), S(0x28d), S(0x28e), S(0x28f), +S(0x290), S(0x291), S(0x292), S(0x293), S(0x294), S(0x295), S(0x296), S(0x297), +S(0x298), S(0x299), S(0x29a), S(0x29b), S(0x29c), S(0x29d), S(0x29e), S(0x29f), +S(0x2a0), S(0x2a1), S(0x2a2), S(0x2a3), S(0x2a4), S(0x2a5), S(0x2a6), S(0x2a7), +S(0x2a8), S(0x2a9), S(0x2aa), S(0x2ab), S(0x2ac), S(0x2ad), S(0x2ae), S(0x2af), +S(0x2b0), S(0x2b1), S(0x2b2), S(0x2b3), S(0x2b4), S(0x2b5), S(0x2b6), S(0x2b7), +S(0x2b8), S(0x2b9), S(0x2ba), S(0x2bb), S(0x2bc), S(0x2bd), S(0x2be), S(0x2bf), +S(0x2c0), S(0x2c1), S(0x2c2), S(0x2c3), S(0x2c4), S(0x2c5), S(0x2c6), S(0x2c7), +S(0x2c8), S(0x2c9), S(0x2ca), S(0x2cb), S(0x2cc), S(0x2cd), S(0x2ce), S(0x2cf), +S(0x2d0), S(0x2d1), S(0x2d2), S(0x2d3), S(0x2d4), S(0x2d5), S(0x2d6), S(0x2d7), +S(0x2d8), S(0x2d9), S(0x2da), S(0x2db), S(0x2dc), S(0x2dd), S(0x2de), S(0x2df), +S(0x2e0), S(0x2e1), S(0x2e2), S(0x2e3), S(0x2e4), S(0x2e5), S(0x2e6), S(0x2e7), +S(0x2e8), S(0x2e9), S(0x2ea), S(0x2eb), S(0x2ec), S(0x2ed), S(0x2ee), S(0x2ef), +S(0x2f0), S(0x2f1), S(0x2f2), S(0x2f3), S(0x2f4), S(0x2f5), S(0x2f6), S(0x2f7), +S(0x2f8), S(0x2f9), S(0x2fa), S(0x2fb), S(0x2fc), S(0x2fd), S(0x2fe), S(0x2ff), +S(0x300), S(0x301), S(0x302), S(0x303), S(0x304), S(0x305), S(0x306), S(0x307), +S(0x308), S(0x309), S(0x30a), S(0x30b), S(0x30c), S(0x30d), S(0x30e), S(0x30f), +S(0x310), S(0x311), S(0x312), S(0x313), S(0x314), S(0x315), S(0x316), S(0x317), +S(0x318), S(0x319), S(0x31a), S(0x31b), S(0x31c), S(0x31d), S(0x31e), S(0x31f), +S(0x320), S(0x321), S(0x322), S(0x323), S(0x324), S(0x325), S(0x326), S(0x327), +S(0x328), S(0x329), S(0x32a), S(0x32b), S(0x32c), S(0x32d), S(0x32e), S(0x32f), +S(0x330), S(0x331), S(0x332), S(0x333), S(0x334), S(0x335), S(0x336), S(0x337), +S(0x338), S(0x339), S(0x33a), S(0x33b), S(0x33c), S(0x33d), S(0x33e), S(0x33f), +S(0x340), S(0x341), S(0x342), S(0x343), S(0x344), S(0x345), S(0x346), S(0x347), +S(0x348), S(0x349), S(0x34a), S(0x34b), S(0x34c), S(0x34d), S(0x34e), S(0x34f), +S(0x350), S(0x351), S(0x352), S(0x353), S(0x354), S(0x355), S(0x356), S(0x357), +S(0x358), S(0x359), S(0x35a), S(0x35b), S(0x35c), S(0x35d), S(0x35e), S(0x35f), +S(0x360), S(0x361), S(0x362), S(0x363), S(0x364), S(0x365), S(0x366), S(0x367), +S(0x368), S(0x369), S(0x36a), S(0x36b), S(0x36c), S(0x36d), S(0x36e), S(0x36f), +S(0x370), S(0x371), S(0x372), S(0x373), S(0x374), S(0x375), S(0x376), S(0x377), +S(0x378), S(0x379), S(0x37a), S(0x37b), S(0x37c), S(0x37d), S(0x37e), S(0x37f), +S(0x380), S(0x381), S(0x382), S(0x383), S(0x384), S(0x385), S(0x386), S(0x387), +S(0x388), S(0x389), S(0x38a), S(0x38b), S(0x38c), S(0x38d), S(0x38e), S(0x38f), +S(0x390), S(0x391), S(0x392), S(0x393), S(0x394), S(0x395), S(0x396), S(0x397), +S(0x398), S(0x399), S(0x39a), S(0x39b), S(0x39c), S(0x39d), S(0x39e), S(0x39f), +S(0x3a0), S(0x3a1), S(0x3a2), S(0x3a3), S(0x3a4), S(0x3a5), S(0x3a6), S(0x3a7), +S(0x3a8), S(0x3a9), S(0x3aa), S(0x3ab), S(0x3ac), S(0x3ad), S(0x3ae), S(0x3af), +S(0x3b0), S(0x3b1), S(0x3b2), S(0x3b3), S(0x3b4), S(0x3b5), S(0x3b6), S(0x3b7), +S(0x3b8), S(0x3b9), S(0x3ba), S(0x3bb), S(0x3bc), S(0x3bd), S(0x3be), S(0x3bf), +S(0x3c0), S(0x3c1), S(0x3c2), S(0x3c3), S(0x3c4), S(0x3c5), S(0x3c6), S(0x3c7), +S(0x3c8), S(0x3c9), S(0x3ca), S(0x3cb), S(0x3cc), S(0x3cd), S(0x3ce), S(0x3cf), +S(0x3d0), S(0x3d1), S(0x3d2), S(0x3d3), S(0x3d4), S(0x3d5), S(0x3d6), S(0x3d7), +S(0x3d8), S(0x3d9), S(0x3da), S(0x3db), S(0x3dc), S(0x3dd), S(0x3de), S(0x3df), +S(0x3e0), S(0x3e1), S(0x3e2), S(0x3e3), S(0x3e4), S(0x3e5), S(0x3e6), S(0x3e7), +S(0x3e8), S(0x3e9), S(0x3ea), S(0x3eb), S(0x3ec), S(0x3ed), S(0x3ee), S(0x3ef), +S(0x3f0), S(0x3f1), S(0x3f2), S(0x3f3), S(0x3f4), S(0x3f5), S(0x3f6), S(0x3f7), +S(0x3f8), S(0x3f9), S(0x3fa), S(0x3fb), S(0x3fc), S(0x3fd), S(0x3fe), S(0x3ff) +}; +#endif /* MAKE_IDENTITY_MAP */ + +/* +** Kernel address mappings, present in every page table +*/ +mapping_t kmap[] = { + // va pa_start pa_end perms + { KERN_BASE, 0, EXT_BASE, PDE_RW }, + { KERN_VLINK, KERN_PLINK, V2P(_data), 0 }, + { (uint32_t) _data, V2P(_data), KERN_BASE, PDE_RW }, + { DEV_BASE, DEV_BASE, 0, PDE_RW } +}; +const uint_t n_kmap = sizeof(kmap) / sizeof(kmap[0]); diff --git a/lib/Make.mk b/lib/Make.mk new file mode 100644 index 0000000..2f8de2c --- /dev/null +++ b/lib/Make.mk @@ -0,0 +1,73 @@ +# +# Makefile fragment for the library components of the system. +# +# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level +# directory, and this will be pulled in automatically. +# + +SUBDIRS += lib + +################### +# FILES SECTION # +################### + +# +# library file lists +# + +# "common" library functions, used by kernel and users +CLIB_SRC := lib/bound.c lib/cvtdec.c lib/cvtdec0.c \ + lib/cvthex.c lib/cvtoct.c lib/cvtuns.c \ + lib/cvtuns0.c lib/memclr.c lib/memcpy.c \ + lib/memset.c lib/pad.c lib/padstr.c \ + lib/sprint.c lib/str2int.c lib/strcat.c \ + lib/strcmp.c lib/strcpy.c lib/strlen.c + +# user-only library functions +ULIB_SRC := lib/ulibc.c lib/ulibs.S lib/entry.S + +# kernel-only library functions +KLIB_SRC := lib/klibc.c + +# lists of object files +CLIB_OBJ:= $(patsubst lib/%.c, $(BUILDDIR)/lib/%.o, $(CLIB_SRC)) + +ULIB_OBJ:= $(patsubst lib/%.c, $(BUILDDIR)/lib/%.o, $(ULIB_SRC)) +ULIB_OBJ:= $(patsubst lib/%.S, $(BUILDDIR)/lib/%.o, $(ULIB_OBJ)) + +KLIB_OBJ := $(patsubst lib/%.c, $(BUILDDIR)/lib/%.o, $(KLIB_SRC)) +KLIB_OBJ := $(patsubst lib/%.S, $(BUILDDIR)/lib/%.o, $(KLIB_OBJ)) + +# library file names +CLIB_NAME := libcommon.a +ULIB_NAME := libuser.a +KLIB_NAME := libkernel.a + +################### +# RULES SECTION # +################### + +# how to make everything +lib: $(BUILDDIR)/lib/$(CLIB_NAME) \ + $(BUILDDIR)/lib/$(KLIB_NAME) \ + $(BUILDDIR)/lib/$(ULIB_NAME) + +$(BUILDDIR)/lib/%.o: lib/%.c $(BUILDDIR)/.vars.CFLAGS + @mkdir -p $(@D) + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILDDIR)/lib/%.o: lib/%.S $(BUILDDIR)/.vars.CFLAGS + @mkdir -p $(@D) + $(CPP) $(CPPFLAGS) -o $(@D)/$*.s $< + $(AS) $(ASFLAGS) -o $@ $(@D)/$*.s -a=$(@D)/$*.lst + $(RM) -f $(@D)/$*.s + $(NM) -n $@ > $(@D)/$*.sym + +$(BUILDDIR)/lib/$(CLIB_NAME): $(CLIB_OBJ) + $(AR) $(ARFLAGS) $@ $(CLIB_OBJ) + +$(BUILDDIR)/lib/$(ULIB_NAME): $(ULIB_OBJ) + $(AR) $(ARFLAGS) $@ $(ULIB_OBJ) + +$(BUILDDIR)/lib/$(KLIB_NAME): $(KLIB_OBJ) + $(AR) $(ARFLAGS) $@ $(KLIB_OBJ) diff --git a/lib/bound.c b/lib/bound.c new file mode 100644 index 0000000..f086473 --- /dev/null +++ b/lib/bound.c @@ -0,0 +1,37 @@ +/** +** @file bound.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef BOUND_SRC_INC +#define BOUND_SRC_INC + +#include + +#include + +/** +** bound(min,value,max) +** +** This function confines an argument within specified bounds. +** +** @param min Lower bound +** @param value Value to be constrained +** @param max Upper bound +** +** @return The constrained value +*/ +uint32_t bound( uint32_t min, uint32_t value, uint32_t max ) { + if( value < min ){ + value = min; + } + if( value > max ){ + value = max; + } + return value; +} + +#endif diff --git a/lib/cvtdec.c b/lib/cvtdec.c new file mode 100644 index 0000000..216f147 --- /dev/null +++ b/lib/cvtdec.c @@ -0,0 +1,43 @@ +/** +** @file cvtdec.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef CVTDEC_SRC_INC +#define CVTDEC_SRC_INC + +#include + +#include + +/** +** cvtdec(buf,value) +** +** convert a 32-bit signed value into a NUL-terminated character string +** +** @param buf Destination buffer +** @param value Value to convert +** +** @return The number of characters placed into the buffer +** (not including the NUL) +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +int cvtdec( char *buf, int32_t value ) { + char *bp = buf; + + if( value < 0 ) { + *bp++ = '-'; + value = -value; + } + + bp = cvtdec0( bp, value ); + *bp = '\0'; + + return( bp - buf ); +} + +#endif diff --git a/lib/cvtdec0.c b/lib/cvtdec0.c new file mode 100644 index 0000000..87792e0 --- /dev/null +++ b/lib/cvtdec0.c @@ -0,0 +1,44 @@ +/** +** @file cvtdec0.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef CVTDEC0_SRC_INC +#define CVTDEC0_SRC_INC + +#include + +#include + +/** +** cvtdec0(buf,value) - local support routine for cvtdec() +** +** convert a 32-bit unsigned integer into a NUL-terminated character string +** +** @param buf Destination buffer +** @param value Value to convert +** +** @return The number of characters placed into the buffer +** (not including the NUL) +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +char *cvtdec0( char *buf, int value ) { + int quotient; + + quotient = value / 10; + if( quotient < 0 ) { + quotient = 214748364; + value = 8; + } + if( quotient != 0 ) { + buf = cvtdec0( buf, quotient ); + } + *buf++ = value % 10 + '0'; + return buf; +} + +#endif diff --git a/lib/cvthex.c b/lib/cvthex.c new file mode 100644 index 0000000..5f3da19 --- /dev/null +++ b/lib/cvthex.c @@ -0,0 +1,49 @@ +/** +** @file cvthex.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef CVTHEX_SRC_INC +#define CVTHEX_SRC_INC + +#include + +#include + +/** +** cvthex(buf,value) +** +** convert a 32-bit unsigned value into a minimal-length (up to +** 8-character) NUL-terminated character string +** +** @param buf Destination buffer +** @param value Value to convert +** +** @return The number of characters placed into the buffer +** (not including the NUL) +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +int cvthex( char *buf, uint32_t value ) { + const char hexdigits[] = "0123456789ABCDEF"; + int chars_stored = 0; + + for( int i = 0; i < 8; i += 1 ) { + uint32_t val = value & 0xf0000000; + if( chars_stored || val != 0 || i == 7 ) { + ++chars_stored; + val = (val >> 28) & 0xf; + *buf++ = hexdigits[val]; + } + value <<= 4; + } + + *buf = '\0'; + + return( chars_stored ); +} + +#endif diff --git a/lib/cvtoct.c b/lib/cvtoct.c new file mode 100644 index 0000000..dafd8ff --- /dev/null +++ b/lib/cvtoct.c @@ -0,0 +1,54 @@ +/** +** @file cvtoct.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef CVTOCT_SRC_INC +#define CVTOCT_SRC_INC + +#include + +#include + +/** +** cvtoct(buf,value) +** +** convert a 32-bit unsigned value into a mininal-length (up to +** 11-character) NUL-terminated character string +** +** @param buf Destination buffer +** @param value Value to convert +** +** @return The number of characters placed into the buffer +** (not including the NUL) +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +int cvtoct( char *buf, uint32_t value ) { + int i; + int chars_stored = 0; + char *bp = buf; + uint32_t val; + + val = ( value & 0xc0000000 ); + val >>= 30; + for( i = 0; i < 11; i += 1 ){ + + if( i == 10 || val != 0 || chars_stored ) { + chars_stored = 1; + val &= 0x7; + *bp++ = val + '0'; + } + value <<= 3; + val = ( value & 0xe0000000 ); + val >>= 29; + } + *bp = '\0'; + + return bp - buf; +} + +#endif diff --git a/lib/cvtuns.c b/lib/cvtuns.c new file mode 100644 index 0000000..a0a686a --- /dev/null +++ b/lib/cvtuns.c @@ -0,0 +1,37 @@ +/** +** @file cvtuns.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef CVTUNS_SRC_INC +#define CVTUNS_SRC_INC + +#include + +#include + +/** +** cvtuns(buf,value) +** +** Convert a 32-bit unsigned value into a NUL-terminated character string +** +** @param buf Result buffer +** @param value Value to be converted +** +** @return Length of the resulting buffer +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +int cvtuns( char *buf, uint32_t value ) { + char *bp = buf; + + bp = cvtuns0( bp, value ); + *bp = '\0'; + + return bp - buf; +} + +#endif diff --git a/lib/cvtuns0.c b/lib/cvtuns0.c new file mode 100644 index 0000000..6a63573 --- /dev/null +++ b/lib/cvtuns0.c @@ -0,0 +1,39 @@ +/** +** @file cvtuns0.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef CVTUNS0_SRC_INC +#define CVTUNS0_SRC_INC + +#include + +#include + +/** +** cvtuns0(buf,value) - local support routine for cvtuns() +** +** Convert a 32-bit unsigned value into a NUL-terminated character string +** +** @param buf Result buffer +** @param value Value to be converted +** +** @return Pointer to the first unused byte in the buffer +** +** NOTE: assumes buf is large enough to hold the resulting string +*/ +char *cvtuns0( char *buf, uint32_t value ) { + uint32_t quotient; + + quotient = value / 10; + if( quotient != 0 ){ + buf = cvtdec0( buf, quotient ); + } + *buf++ = value % 10 + '0'; + return buf; +} + +#endif diff --git a/lib/entry.S b/lib/entry.S new file mode 100644 index 0000000..87ad9c7 --- /dev/null +++ b/lib/entry.S @@ -0,0 +1,25 @@ +// +// user-level startup routine +// + .text + .globl _start + .globl main + .globl exit + +// entry point - this is where the kernel starts us running +_start: + // we immediately call main() + call main + + // if we come back from that, it means the user + // program didn't call exit(), in which case the + // value returned from main() is the exit status + + // push that value onto the stack and call exit() + subl $12, %esp + pushl %eax + call exit + + // if we come back from that, something bad has + // happened, so we just lock up +1: jmp 1b diff --git a/lib/klibc.c b/lib/klibc.c new file mode 100644 index 0000000..ded0c78 --- /dev/null +++ b/lib/klibc.c @@ -0,0 +1,112 @@ +/* +** @file klibc.c +** +** @author Warren R. Carithers +** +** Additional support functions for the kernel. +** +*/ + +#define KERNEL_SRC + +#include +#include +#include +#include + +/** +** Name: put_char_or_code( ch ) +** +** Description: Prints a character on the console, unless it +** is a non-printing character, in which case its hex code +** is printed +** +** @param ch The character to be printed +*/ +void put_char_or_code( int ch ) { + + if( ch >= ' ' && ch < 0x7f ) { + cio_putchar( ch ); + } else { + cio_printf( "\\x%02x", ch ); + } +} + +/** +** Name: backtrace +** +** Perform a stack backtrace +** +** @param ebp Initial EBP to use +** @param args Number of function argument values to print +*/ +void backtrace( uint32_t *ebp, uint_t args ) { + + cio_puts( "Trace: " ); + if( ebp == NULL ) { + cio_puts( "NULL ebp, no trace possible\n" ); + return; + } else { + cio_putchar( '\n' ); + } + + while( ebp != NULL ){ + + // get return address and report it and EBP + uint32_t ret = ebp[1]; + cio_printf( " ebp %08x ret %08x args", (uint32_t) ebp, ret ); + + // print the requested number of function arguments + for( uint_t i = 0; i < args; ++i ) { + cio_printf( " [%u] %08x", i+1, ebp[2+i] ); + } + cio_putchar( '\n' ); + + // follow the chain + ebp = (uint32_t *) *ebp; + } +} + +/** +** kpanic - kernel-level panic routine +** +** usage: kpanic( msg ) +** +** Prefix routine for panic() - can be expanded to do other things +** (e.g., printing a stack traceback) +** +** @param msg[in] String containing a relevant message to be printed, +** or NULL +*/ +void kpanic( const char *msg ) { + + cio_puts( "\n\n***** KERNEL PANIC *****\n\n" ); + + if( msg ) { + cio_printf( "%s\n", msg ); + } + + delay( DELAY_5_SEC ); // approximately + + // dump a bunch of potentially useful information + + // dump the contents of the current PCB + pcb_dump( "Current", current, true ); + + // dump the basic info about what's in the process table + ptable_dump_counts(); + + // dump information about the queues + pcb_queue_dump( "R", ready, true ); + pcb_queue_dump( "W", waiting, true ); + pcb_queue_dump( "S", sleeping, true ); + pcb_queue_dump( "Z", zombie, true ); + pcb_queue_dump( "I", sioread, true ); + + // perform a stack backtrace + backtrace( (uint32_t *) r_ebp(), 3 ); + + // could dump other stuff here, too + + panic( "KERNEL PANIC" ); +} diff --git a/lib/memclr.c b/lib/memclr.c new file mode 100644 index 0000000..490fc6d --- /dev/null +++ b/lib/memclr.c @@ -0,0 +1,37 @@ +/** +** @file memclr.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef MEMCLR_SRC_INC +#define MEMCLR_SRC_INC + +#include + +#include + +/** +** memclr(buf,len) +** +** Initialize all bytes of a block of memory to zero +** +** @param buf The buffer to initialize +** @param len Buffer size (in bytes) +*/ +void memclr( void *buf, register uint32_t len ) { + register uint8_t *dest = buf; + + /* + ** We could speed this up by unrolling it and clearing + ** words at a time (instead of bytes). + */ + + while( len-- ) { + *dest++ = 0; + } +} + +#endif diff --git a/lib/memcpy.c b/lib/memcpy.c new file mode 100644 index 0000000..e5add26 --- /dev/null +++ b/lib/memcpy.c @@ -0,0 +1,41 @@ +/** +** @file memcpy.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef MEMCPY_SRC_INC +#define MEMCPY_SRC_INC + +#include + +#include + +/** +** memcpy(dst,src,len) +** +** Copy a block from one place to another +** +** May not correctly deal with overlapping buffers +** +** @param dst Destination buffer +** @param src Source buffer +** @param len Buffer size (in bytes) +*/ +void memcpy( void *dst, register const void *src, register uint32_t len ) { + register uint8_t *dest = dst; + register const uint8_t *source = src; + + /* + ** We could speed this up by unrolling it and copying + ** words at a time (instead of bytes). + */ + + while( len-- ) { + *dest++ = *source++; + } +} + +#endif diff --git a/lib/memset.c b/lib/memset.c new file mode 100644 index 0000000..a93815c --- /dev/null +++ b/lib/memset.c @@ -0,0 +1,38 @@ +/** +** @file memset.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef MEMSET_SRC_INC +#define MEMSET_SRC_INC + +#include + +#include + +/** +** memset(buf,len,value) +** +** initialize all bytes of a block of memory to a specific value +** +** @param buf The buffer to initialize +** @param len Buffer size (in bytes) +** @param value Initialization value +*/ +void memset( void *buf, register uint32_t len, register uint32_t value ) { + register uint8_t *bp = buf; + + /* + ** We could speed this up by unrolling it and copying + ** words at a time (instead of bytes). + */ + + while( len-- ) { + *bp++ = value; + } +} + +#endif diff --git a/lib/pad.c b/lib/pad.c new file mode 100644 index 0000000..5220c99 --- /dev/null +++ b/lib/pad.c @@ -0,0 +1,35 @@ +/** +** @file pad.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef PAD_SRC_INC +#define PAD_SRC_INC + +#include + +#include + +/** +** pad(dst,extra,padchar) - generate a padding string +** +** @param dst Pointer to where the padding should begin +** @param extra How many padding bytes to add +** @param padchar What character to pad with +** +** @return Pointer to the first byte after the padding +** +** NOTE: does NOT NUL-terminate the buffer +*/ +char *pad( char *dst, int extra, int padchar ) { + while( extra > 0 ){ + *dst++ = (char) padchar; + extra -= 1; + } + return dst; +} + +#endif diff --git a/lib/padstr.c b/lib/padstr.c new file mode 100644 index 0000000..b83229f --- /dev/null +++ b/lib/padstr.c @@ -0,0 +1,61 @@ +/** +** @file padstr.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef PADSTR_SRC_INC +#define PADSTR_SRC_INC + +#include + +#include + +/** +** padstr(dst,str,len,width,leftadjust,padchar - add padding characters +** to a string +** +** @param dst The destination buffer +** @param str The string to be padded +** @param len The string length, or -1 +** @param width The desired final length of the string +** @param leftadjust Should the string be left-justified? +** @param padchar What character to pad with +** +** @return Pointer to the first byte after the padded string +** +** NOTE: does NOT NUL-terminate the buffer +*/ +char *padstr( char *dst, char *str, int len, int width, + int leftadjust, int padchar ) { + int extra; + + // determine the length of the string if we need to + if( len < 0 ){ + len = strlen( str ); + } + + // how much filler must we add? + extra = width - len; + + // add filler on the left if we're not left-justifying + if( extra > 0 && !leftadjust ){ + dst = pad( dst, extra, padchar ); + } + + // copy the string itself + for( int i = 0; i < len; ++i ) { + *dst++ = str[i]; + } + + // add filler on the right if we are left-justifying + if( extra > 0 && leftadjust ){ + dst = pad( dst, extra, padchar ); + } + + return dst; +} + +#endif diff --git a/lib/sprint.c b/lib/sprint.c new file mode 100644 index 0000000..d2e0a7e --- /dev/null +++ b/lib/sprint.c @@ -0,0 +1,133 @@ +/** +** @file sprint.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef SPRINT_SRC_INC +#define SPRINT_SRC_INC + +#include + +#include + +/** +** sprint(dst,fmt,...) - formatted output into a string buffer +** +** @param dst The string buffer +** @param fmt Format string +** +** The format string parameter is followed by zero or more additional +** parameters which are interpreted according to the format string. +** +** NOTE: assumes the buffer is large enough to hold the result string +** +** NOTE: relies heavily on the x86 parameter passing convention +** (parameters are pushed onto the stack in reverse order as +** 32-bit values). +*/ +void sprint( char *dst, char *fmt, ... ) { + int32_t *ap; + char buf[ 12 ]; + char ch; + char *str; + int leftadjust; + int width; + int len; + int padchar; + + /* + ** Get characters from the format string and process them + ** + ** We use the "old-school" method of handling variable numbers + ** of parameters. We assume that parameters are passed on the + ** runtime stack in consecutive longwords; thus, if the first + ** parameter is at location 'x', the second is at 'x+4', the + ** third at 'x+8', etc. We use a pointer to a 32-bit thing + ** to point to the next "thing", and interpret it according + ** to the format string. + */ + + // get the pointer to the first "value" parameter + ap = (int *)(&fmt) + 1; + + // iterate through the format string + while( (ch = *fmt++) != '\0' ){ + /* + ** Is it the start of a format code? + */ + if( ch == '%' ){ + /* + ** Yes, get the padding and width options (if there). + ** Alignment must come at the beginning, then fill, + ** then width. + */ + leftadjust = 0; + padchar = ' '; + width = 0; + ch = *fmt++; + if( ch == '-' ){ + leftadjust = 1; + ch = *fmt++; + } + if( ch == '0' ){ + padchar = '0'; + ch = *fmt++; + } + while( ch >= '0' && ch <= '9' ){ + width *= 10; + width += ch - '0'; + ch = *fmt++; + } + + /* + ** What data type do we have? + */ + switch( ch ) { + + case 'c': // characters are passed as 32-bit values + ch = *ap++; + buf[ 0 ] = ch; + buf[ 1 ] = '\0'; + dst = padstr( dst, buf, 1, width, leftadjust, padchar ); + break; + + case 'd': + len = cvtdec( buf, *ap++ ); + dst = padstr( dst, buf, len, width, leftadjust, padchar ); + break; + + case 's': + str = (char *) (*ap++); + dst = padstr( dst, str, -1, width, leftadjust, padchar ); + break; + + case 'x': + len = cvthex( buf, *ap++ ); + dst = padstr( dst, buf, len, width, leftadjust, padchar ); + break; + + case 'o': + len = cvtoct( buf, *ap++ ); + dst = padstr( dst, buf, len, width, leftadjust, padchar ); + break; + + case 'u': + len = cvtuns( buf, *ap++ ); + dst = padstr( dst, buf, len, width, leftadjust, padchar ); + break; + + } + } else { + // no, it's just an ordinary character + *dst++ = ch; + } + } + + // NUL-terminate the result + *dst = '\0'; +} + +#endif diff --git a/lib/str2int.c b/lib/str2int.c new file mode 100644 index 0000000..c0f777d --- /dev/null +++ b/lib/str2int.c @@ -0,0 +1,51 @@ +/** +** @file str2int.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef STR2INT_SRC_INC +#define STR2INT_SRC_INC + +#include + +#include + +/** +** str2int(str,base) - convert a string to a number in the specified base +** +** @param str The string to examine +** @param base The radix to use in the conversion +** +** @return The converted integer +*/ +int str2int( register const char *str, register int base ) { + register int num = 0; + register char bchar = '9'; + int sign = 1; + + // check for leading '-' + if( *str == '-' ) { + sign = -1; + ++str; + } + + if( base != 10 ) { + bchar = '0' + base - 1; + } + + // iterate through the characters + while( *str ) { + if( *str < '0' || *str > bchar ) + break; + num = num * base + *str - '0'; + ++str; + } + + // return the converted value + return( num * sign ); +} + +#endif diff --git a/lib/strcat.c b/lib/strcat.c new file mode 100644 index 0000000..b0a8726 --- /dev/null +++ b/lib/strcat.c @@ -0,0 +1,38 @@ +/** +** @file strcat.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef STRCAT_SRC_INC +#define STRCAT_SRC_INC + +#include + +#include + +/** +** strcat(dst,src) - append one string to another +** +** @param dst The destination buffer +** @param src The source buffer +** +** @return The dst parameter +** +** NOTE: assumes dst is large enough to hold the resulting string +*/ +char *strcat( register char *dst, register const char *src ) { + register char *tmp = dst; + + while( *dst ) // find the NUL + ++dst; + + while( (*dst++ = *src++) ) // append the src string + ; + + return( tmp ); +} + +#endif diff --git a/lib/strcmp.c b/lib/strcmp.c new file mode 100644 index 0000000..c59f4f7 --- /dev/null +++ b/lib/strcmp.c @@ -0,0 +1,32 @@ +/** +** @file strcmp.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef STRCMP_SRC_INC +#define STRCMP_SRC_INC + +#include + +#include + +/** +** strcmp(s1,s2) - compare two NUL-terminated strings +** +** @param s1 The first source string +** @param s2 The second source string +** +** @return negative if s1 < s2, zero if equal, and positive if s1 > s2 +*/ +int strcmp( register const char *s1, register const char *s2 ) { + + while( *s1 != 0 && (*s1 == *s2) ) + ++s1, ++s2; + + return( *s1 - *s2 ); +} + +#endif diff --git a/lib/strcpy.c b/lib/strcpy.c new file mode 100644 index 0000000..036e4be --- /dev/null +++ b/lib/strcpy.c @@ -0,0 +1,35 @@ +/** +** @file strcpy.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef STRCPY_SRC_INC +#define STRCPY_SRC_INC + +#include + +#include + +/** +** strcpy(dst,src) - copy a NUL-terminated string +** +** @param dst The destination buffer +** @param src The source buffer +** +** @return The dst parameter +** +** NOTE: assumes dst is large enough to hold the copied string +*/ +char *strcpy( register char *dst, register const char *src ) { + register char *tmp = dst; + + while( (*dst++ = *src++) ) + ; + + return( tmp ); +} + +#endif diff --git a/lib/strlen.c b/lib/strlen.c new file mode 100644 index 0000000..b41fe69 --- /dev/null +++ b/lib/strlen.c @@ -0,0 +1,32 @@ +/** +** @file strlen.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +*/ + +#ifndef STRLEN_SRC_INC +#define STRLEN_SRC_INC + +#include + +#include + +/** +** strlen(str) - return length of a NUL-terminated string +** +** @param str The string to examine +** +** @return The length of the string, or 0 +*/ +uint32_t strlen( register const char *str ) { + register uint32_t len = 0; + + while( *str++ ) { + ++len; + } + + return( len ); +} +#endif diff --git a/lib/ulibc.c b/lib/ulibc.c new file mode 100644 index 0000000..f3783a4 --- /dev/null +++ b/lib/ulibc.c @@ -0,0 +1,162 @@ +/** +** @file ulibc.c +** +** @author CSCI-452 class of 20245 +** +** @brief C implementations of user-level library functions +*/ + +#include + +/* +** PRIVATE DEFINITIONS +*/ + +/* +** PRIVATE DATA TYPES +*/ + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +/* +** PUBLIC GLOBAL VARIABLES +*/ + +/* +** PRIVATE FUNCTIONS +*/ + +/* +** PUBLIC FUNCTIONS +*/ + +/* +********************************************** +** CONVENIENT "SHORTHAND" VERSIONS OF SYSCALLS +********************************************** +*/ + +/** +** wait - wait for any child to exit +** +** usage: pid = wait(&status) +** +** Calls waitpid(0,status) +** +** @param status Pointer to int32_t into which the child's status is placed, +** or NULL +** +** @returns The PID of the terminated child, or an error code +*/ +int wait( int32_t *status ) { + return( waitpid(0,status) ); +} + +/** +** spawn - create a new process running a different program +** +** usage: pid = spawn(what,args); +** +** Creates a new process and then execs 'what' +** +** @param what The program table index of the program to spawn +** @param args The command-line argument vector for the new process +** +** @returns PID of the new process, or an error code +*/ +int32_t spawn( uint_t what, char **args ) { + int32_t pid; + char buf[256]; + + pid = fork(); + if( pid != 0 ) { + // failure, or we are the parent + return( pid ); + } + + // we are the child + pid = getpid(); + + // child inherits parent's priority level + + exec( what, args ); + + // uh-oh.... + + sprint( buf, "Child %d exec() #%u failed\n", pid, what ); + cwrites( buf ); + + exit( EXIT_FAILURE ); + return( 0 ); // shut the compiler up +} + +/** +** cwritech(ch) - write a single character to the console +** +** @param ch The character to write +** +** @returns The return value from calling write() +*/ +int cwritech( char ch ) { + return( write(CHAN_CIO,&ch,1) ); +} + +/** +** cwrites(str) - write a NUL-terminated string to the console +** +** @param str The string to write +** +*/ +int cwrites( const char *str ) { + int len = strlen(str); + return( write(CHAN_CIO,str,len) ); +} + +/** +** cwrite(buf,size) - write a sized buffer to the console +** +** @param buf The buffer to write +** @param size The number of bytes to write +** +** @returns The return value from calling write() +*/ +int cwrite( const char *buf, uint32_t size ) { + return( write(CHAN_CIO,buf,size) ); +} + +/** +** swritech(ch) - write a single character to the SIO +** +** @param ch The character to write +** +** @returns The return value from calling write() +*/ +int swritech( char ch ) { + return( write(CHAN_SIO,&ch,1) ); +} + +/** +** swrites(str) - write a NUL-terminated string to the SIO +** +** @param str The string to write +** +** @returns The return value from calling write() +*/ +int swrites( const char *str ) { + int len = strlen(str); + return( write(CHAN_SIO,str,len) ); +} + +/** +** swrite(buf,size) - write a sized buffer to the SIO +** +** @param buf The buffer to write +** @param size The number of bytes to write +** +** @returns The return value from calling write() +*/ +int swrite( const char *buf, uint32_t size ) { + return( write(CHAN_SIO,buf,size) ); +} diff --git a/lib/ulibs.S b/lib/ulibs.S new file mode 100644 index 0000000..46fcb89 --- /dev/null +++ b/lib/ulibs.S @@ -0,0 +1,93 @@ +/** +** @file ulibs.S +** +** @author CSCI-452 class of 20245 +** +** @brief assembly-language user-level library functions +*/ + +#define ASM_SRC + +// get the system call codes + +#include + +/** +** System call stubs +** +** All have the same structure: +** +** move a code into EAX +** generate the interrupt +** return to the caller +** +** As these are simple "leaf" routines, we don't use +** the standard enter/leave method to set up a stack +** frame - that takes time, and we don't really need it. +** +** Could be modified to use the UNIX/Linux convention of +** having the syscall code set the 'C' flag to indicate that +** the value being returned in %EAX is an error code: +** +** ... +** int $VEC_SYSCALL +** jc set_errno +** ret +** ... +** +** .globl errno +** set_errno: +** movl %eax, errno +** movl $-1, %eax +** ret +*/ + +#define SYSCALL(name) \ + .globl name ; \ +name: ; \ + movl $SYS_##name, %eax ; \ + int $VEC_SYSCALL ; \ + ret + +/* +** "real" system calls +*/ + +SYSCALL(exit) +SYSCALL(waitpid) +SYSCALL(fork) +SYSCALL(exec) +SYSCALL(read) +SYSCALL(write) +SYSCALL(getpid) +SYSCALL(getppid) +SYSCALL(gettime) +SYSCALL(getprio) +SYSCALL(setprio) +SYSCALL(kill) +SYSCALL(sleep) + +/* +** This is a bogus system call; it's here so that we can test +** our handling of out-of-range syscall codes in the syscall ISR. +*/ +SYSCALL(bogus) + +/* +** Other library functions +*/ + +/** +** fake_exit() +** +** Dummy "startup" function +** +** calls exit(%eax) - serves as the "return to" code for +** main() functions, in case they don't call exit() themselves +*/ + + .globl fake_exit +fake_exit: + // alternate: could push a "fake exit" status + pushl %eax // termination status returned by main() + call exit // terminate this process diff --git a/user/Make.mk b/user/Make.mk new file mode 100644 index 0000000..648de69 --- /dev/null +++ b/user/Make.mk @@ -0,0 +1,64 @@ +# +# Makefile fragment for the user components of the system. +# +# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level +# directory, and this will be pulled in automatically. +# + +SUBDIRS += user + +################### +# FILES SECTION # +################### + +# order here must match the order of program names in the +# 'user_e' enum defined in include/userids.h!!! +USER_SRC := user/init.c user/idle.c user/shell.c \ + user/progABC.c user/progDE.c user/progFG.c user/progH.c \ + user/progI.c user/progJ.c user/progKL.c user/progMN.c \ + user/progP.c user/progQ.c user/progR.c user/progS.c \ + user/progTUV.c user/progW.c user/progX.c user/progY.c \ + user/progZ.c + +USER_OBJ := $(patsubst %.c, $(BUILDDIR)/%.o, $(USER_SRC)) + +USER_BIN := $(basename $(USER_SRC)) +USER_BIN := $(addprefix $(BUILDDIR)/, $(USER_BIN)) + +ULDFLAGS := -T user/user.ld +ULIBS := -luser -lcommon + +################### +# RULES SECTION # +################### + +userland: $(USER_BIN) + +$(BUILDDIR)/user/%.o: user/%.c $(BUILDDIR)/.vars.CFLAGS + @mkdir -p $(@D) + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILDDIR)/user/%: $(BUILDDIR)/user/%.o + @mkdir -p $(@D) + $(LD) $(ULDFLAGS) $(LDFLAGS) -o $@ $@.o $(ULIBS) + $(OBJDUMP) -S $@ > $@.asm + $(NM) -n $@ > $@.sym + $(READELF) -a $@ > $@.info + +# +# Remake the "user blob". When this happens, we also generate a new +# version of the userids.h header file; we don't copy it over the +# previous version if it is the same, to avoid triggering remakes +# of the rest of the system. +# +user.img: $(USR_BIN) mkblob + ./mkblob $(USER_BIN) + @./listblob -e $@ > $(BUILDDIR)/new_userids.h + -@sh -c 'cmp -s include/userids.h $(BUILDDIR)/new_userids.h || \ + (cp $(BUILDDIR)/new_userids.h include/userids.h; \ + echo "\n*** NOTE - updated include/userids.h, rebuild\!" ; \ + rm -f $(BUILDDIR)/new_userids.h)' + +# some debugging assist rules +user.hex: user.img + hexdump -C $< > $@ diff --git a/user/README b/user/README new file mode 100644 index 0000000..548aac4 --- /dev/null +++ b/user/README @@ -0,0 +1,25 @@ +This directory contains the source code for all user-level processes, +split out by main function. + +Naming convention: + + idle() classic 'idle' process; ensures there is always a + runnable process to dispatch (vs., for instance, having + dispatch() pause when there is nothing to dispatch). + + init() classic 'init' process; starts the idle process, and + starts (and restarts) the user shell program. + + shell() "user shell" process, for spawning individual tests + + progN() program source code for user process(es) 'N' + +All of these expect at least one command-line argument. All are invoked +with command lines of this form: + + name x n + +Each of these is designed to be compiled and linked separately, with the +resulting load modules bundled into a blob for automatic loading by the +bootstrap. Each will typically use one or more library functions from the +../lib directory. diff --git a/user/idle.c b/user/idle.c new file mode 100644 index 0000000..dbce885 --- /dev/null +++ b/user/idle.c @@ -0,0 +1,51 @@ +#include + +/** +** Idle process: write, getpid, gettime, exit +** +** Reports itself, then loops forever delaying and printing a character. +** MUST NOT SLEEP, as it must always be available in the ready queue +** when there is no other process to dispatch. +** +** Invoked as: idle +*/ + +USERMAIN( main ) { + // this is the character we will repeatedly print + char ch = '.'; + + // ignore the command-line arguments + (void) argc; + (void) argv; + + // get some current information + uint_t pid = getpid(); + uint32_t now = gettime(); + enum priority_e prio = getprio(); + + char buf[128]; + sprint( buf, "Idle [%d], started @ %u\n", pid, prio, now ); + cwrites( buf ); + + // report our presence on the console + cwrites( "Idle started\n" ); + + write( CHAN_SIO, &ch, 1 ); + + // idle() should never block - it must always be available + // for dispatching when we need to pick a new current process + + for(;;) { + DELAY(LONG); + write( CHAN_SIO, &ch, 1 ); + } + + // we should never reach this point! + now = gettime(); + sprint( buf, "Idle [%d] EXITING @ %u!?!?!\n", pid, now ); + cwrites( buf ); + + exit( 1 ); + + return( 42 ); +} diff --git a/user/init.c b/user/init.c new file mode 100644 index 0000000..56330b1 --- /dev/null +++ b/user/init.c @@ -0,0 +1,185 @@ +#include + +/** +** Initial process; it starts the other top-level user processes. +** +** Prints a message at startup, '+' after each user process is spawned, +** and '!' before transitioning to wait() mode to the SIO, and +** startup and transition messages to the console. It also reports +** each child process it collects via wait() to the console along +** with that child's exit status. +*/ + +/* +** "Spawn table" process entry. Similar to the one in shell.c, but +** this version has a field to hold the PID of the spawned process +** to allow 'init' to respawn it when it terminates. +*/ +typedef struct proc_s { + uint_t index; // process table index + uint_t pid; // its PID (when spawned) + uint8_t e_prio; // process priority + char select[3]; // identifying character, NUL, extra + char *args[MAX_ARGS]; // argument vector strings +} proc_t; + +/* +** Create a spawn table entry for a process with a string literal +** as its argument buffer. We rely on the fact that the C standard +** ensures our array of pointers will be filled out with NULLs +*/ +#define PROCENT(e,p,s,...) { e, 0, p, s, { __VA_ARGS__ , NULL } } + +// sentinel value for the end of the table - must be updated +// if you have more than 90,210 user programs in the table +#define TBLEND 90210 + +/* +** This table contains one entry for each process that should be +** started by 'init'. Typically, this includes the 'idle' process +** and a 'shell' process. +*/ +static proc_t spawn_table[] = { + + // the idle process; it runs at Deferred priority, + // so it will only be dispatched when there is + // nothing else available to be dispatched + PROCENT( Idle, PRIO_DEFERRED, "!", "idle", "." ), + + // the user shell + PROCENT( Shell, PRIO_STD, "@", "shell" ), + + // PROCENT( 0, 0, 0, 0 ) + { TBLEND } +}; + +// character to be printed by init when it spawns a process +static char ch = '+'; + +/** +** process - spawn all user processes listed in the supplied table +** +** @param proc pointer to the spawn table entry to be used +*/ + +static void process( proc_t *proc ) +{ + char buf[128]; + + // kick off the process + int32_t p = fork(); + if( p < 0 ) { + + // error! + sprint( buf, "INIT: fork for #%d failed\n", + (uint32_t) (proc->index) ); + cwrites( buf ); + + } else if( p == 0 ) { + + // change child's priority + (void) setprio( proc->e_prio ); + + // now, send it on its way + exec( proc->index, proc->args ); + + // uh-oh - should never get here! + sprint( buf, "INIT: exec(0x%08x) failed\n", + (uint32_t) (proc->index) ); + cwrites( buf ); + + } else { + + // parent just reports that another one was started + swritech( ch ); + + proc->pid = p; + + } +} + +/* +** The initial user process. Should be invoked with zero or one +** argument; if provided, the first argument should be the ASCII +** character 'init' will print to indicate the spawning of a process. +*/ +USERMAIN( main ) { + char buf[128]; + + // check to see if we got a non-standard "spawn" character + if( argc > 1 ) { + // maybe - check it to be sure it's printable + uint_t i = argv[1][0]; + if( i > ' ' && i < 0x7f ) { + ch = argv[1][0]; + } + } + + cwrites( "Init started\n" ); + + // home up, clear on a TVI 925 + swritech( '\x1a' ); + + // wait a bit + DELAY(SHORT); + + // a bit of Dante to set the mood :-) + swrites( "\n\nSpem relinquunt qui huc intrasti!\n\n\r" ); + + /* + ** Start all the user processes + */ + + cwrites( "INIT: starting user processes\n" ); + + proc_t *next; + for( next = spawn_table; next->index != TBLEND; ++next ) { + process( next ); + } + + swrites( " !!!\r\n\n" ); + + /* + ** At this point, we go into an infinite loop waiting + ** for our children (direct, or inherited) to exit. + */ + + cwrites( "INIT: transitioning to wait() mode\n" ); + + for(;;) { + int32_t status; + int whom = waitpid( 0, &status ); + + // PIDs must be positive numbers! + if( whom <= 0 ) { + sprint( buf, "INIT: waitpid() returned %d???\n", whom ); + cwrites( buf ); + } else { + + // got one; report it + sprint( buf, "INIT: pid %d exit(%d)\n", whom, status ); + cwrites( buf ); + + // figure out if this is one of ours + for( next = spawn_table; next->index != TBLEND; ++next ) { + if( next->pid == whom ) { + // one of ours - reset the PID field + // (in case the spawn attempt fails) + next->pid = 0; + // and restart it + process( next ); + break; + } + } + } + } + + /* + ** SHOULD NEVER REACH HERE + */ + + cwrites( "*** INIT IS EXITING???\n" ); + exit( 1 ); + + return( 1 ); // shut the compiler up +} diff --git a/user/progABC.c b/user/progABC.c new file mode 100644 index 0000000..4f7b6e6 --- /dev/null +++ b/user/progABC.c @@ -0,0 +1,68 @@ +#include + +/** +** User function main #1: exit, write +** +** Prints its ID, then loops N times delaying and printing, then exits. +** Verifies the return byte count from each call to write(). +** +** Invoked as: main1 x n +** where x is the ID character +** n is the iteration count +*/ + +USERMAIN( main ) { + int count = 30; // default iteration count + char ch = '1'; // default character to print + char buf[128]; // local char buffer + + // process the command-line arguments + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "%s: argc %d, args: ", argv[0], argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + int n = swritech( ch ); + if( n != 1 ) { + sprint( buf, "== %c, write #1 returned %d\n", ch, n ); + cwrites( buf ); + } + + // iterate and print the required number of other characters + for( int i = 0; i < count; ++i ) { + DELAY(STD); + n = swritech( ch ); + if( n != 1 ) { + sprint( buf, "== %c, write #2 returned %d\n", ch, n ); + cwrites( buf ); + } + } + + // all done! + exit( 0 ); + + // should never reach this code; if we do, something is + // wrong with exit(), so we'll report it + + char msg[] = "*1*"; + msg[1] = ch; + n = write( CHAN_SIO, msg, 3 ); /* shouldn't happen! */ + if( n != 3 ) { + sprint( buf, "User %c, write #3 returned %d\n", ch, n ); + cwrites( buf ); + } + + // this should really get us out of here + return( 42 ); +} diff --git a/user/progDE.c b/user/progDE.c new file mode 100644 index 0000000..a1aa0b3 --- /dev/null +++ b/user/progDE.c @@ -0,0 +1,56 @@ +#include + +/** +** User function main #2: write +** +** Prints its ID, then loops N times delaying and printing, then returns +** without calling exit(). Verifies the return byte count from each call +** to write(). +** +** Invoked as: main2 x n +** where x is the ID character +** n is the iteration count +*/ + +USERMAIN( main ) { + int n; + int count = 30; // default iteration count + char ch = '2'; // default character to print + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "main2: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + n = swritech( ch ); + if( n != 1 ) { + sprint( buf, "== %c, write #1 returned %d\n", ch, n ); + cwrites( buf ); + } + + // iterate and print the required number of other characters + for( int i = 0; i < count; ++i ) { + DELAY(STD); + n = swritech( ch ); + if( n != 1 ) { + sprint( buf, "== %c, write #2 returned %d\n", ch, n ); + cwrites( buf ); + } + } + + // all done! + return( 0 ); +} diff --git a/user/progFG.c b/user/progFG.c new file mode 100644 index 0000000..a43ca67 --- /dev/null +++ b/user/progFG.c @@ -0,0 +1,55 @@ +#include + +/** +** User function main #3: exit, sleep, write +** +** Prints its ID, then loops N times sleeping and printing, then exits. +** +** Invoked as: main3 x n s +** where x is the ID character +** n is the iteration count +** s is the sleep time in seconds +*/ + +USERMAIN( main ) { + char ch = '3'; // default character to print + int nap = 10; // default sleep time + int count = 30; // iteration count + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 4: nap = str2int( argv[3], 10 ); + // FALL THROUGH + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "main3: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + int n = swritech( ch ); + if( n != 1 ) { + sprint( buf, "=== %c, write #1 returned %d\n", ch, n ); + cwrites( buf ); + } + + write( CHAN_SIO, &ch, 1 ); + + for( int i = 0; i < count ; ++i ) { + sleep( SEC_TO_MS(nap) ); + write( CHAN_SIO, &ch, 1 ); + } + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progH.c b/user/progH.c new file mode 100644 index 0000000..386144d --- /dev/null +++ b/user/progH.c @@ -0,0 +1,66 @@ +#include + +/** +** User function H: exit, fork, exec, sleep, write +** +** Prints its ID, then spawns 'n' children; exits before they terminate. +** +** Invoked as: userH x n +** where x is the ID character +** n is the number of children to spawn +*/ + +USERMAIN( main ) { + int32_t ret = 0; // return value + int count = 5; // child count + char ch = 'h'; // default character to print + char buf[128]; + int whom; + + // process the argument(s) + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userH: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + swritech( ch ); + + // we spawn user Z and then exit before it can terminate + // userZ 'Z' 10 + + char *argsz[] = { "userZ", "Z", "10", NULL }; + + for( int i = 0; i < count; ++i ) { + + // spawn a child + whom = spawn( ProgZ, argsz ); + + // our exit status is the number of failed spawn() calls + if( whom < 0 ) { + sprint( buf, "!! %c spawn() failed, returned %d\n", ch, whom ); + cwrites( buf ); + ret += 1; + } + } + + // yield the CPU so that our child(ren) can run + sleep( 0 ); + + // announce our departure + swritech( ch ); + + exit( ret ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progI.c b/user/progI.c new file mode 100644 index 0000000..c37eddf --- /dev/null +++ b/user/progI.c @@ -0,0 +1,104 @@ +#include + +#ifndef MAX_CHILDREN +#define MAX_CHILDREN 50 +#endif + +/** +** User function I: exit, fork, exec, kill, sleep, waitpid, write +** +** Reports, then loops spawing userW, sleeps, kills two children, then +** loops checking the status of all its children +** +** Invoked as: userI [ x [ n ] ] +** where x is the ID character (defaults to 'i') +** n is the number of children to spawn (defaults to 5) +*/ + +USERMAIN( main ) { + int count = 5; // default child count + char ch = 'i'; // default character to print + int nap = 5; // nap time + char buf[128]; + char ch2[] = "*?*"; + uint_t children[MAX_CHILDREN]; + int nkids = 0; + + // process the command-line arguments + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + case 1: // just use the defaults + break; + default: + sprint( buf, "userI: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // secondary output (for indicating errors) + ch2[1] = ch; + + // announce our presence + write( CHAN_SIO, &ch, 1 ); + + // set up the argument vector + // we run: userW 10 5 + + char *argsw[] = { "userW", "W", "10", "5", NULL }; + + for( int i = 0; i < count; ++i ) { + int whom = spawn( ProgW, argsw ); + if( whom < 0 ) { + swrites( ch2 ); + } else { + swritech( ch ); + children[nkids++] = whom; + } + } + + // let the children start + sleep( SEC_TO_MS(nap) ); + + // kill two of them + int32_t status = kill( children[1] ); + if( status ) { + sprint( buf, "!! %c: kill(%d) status %d\n", ch, children[1], status ); + cwrites( buf ); + children[1] = -42; + } + status = kill( children[3] ); + if( status ) { + sprint( buf, "!! %c: kill(%d) status %d\n", ch, children[3], status ); + cwrites( buf ); + children[3] = -42; + } + + // collect child information + while( 1 ) { + int n = waitpid( 0, NULL ); + if( n == E_NO_CHILDREN ) { + // all done! + break; + } + for( int i = 0; i < count; ++i ) { + if( children[i] == n ) { + sprint( buf, "== %c: child %d (%d)\n", ch, i, children[i] ); + cwrites( buf ); + } + } + sleep( SEC_TO_MS(nap) ); + }; + + // let init() clean up after us! + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progJ.c b/user/progJ.c new file mode 100644 index 0000000..6eb4464 --- /dev/null +++ b/user/progJ.c @@ -0,0 +1,52 @@ +#include + +/** +** User function J: exit, fork, exec, write +** +** Reports, tries to spawn lots of children, then exits +** +** Invoked as: userJ x [ n ] +** where x is the ID character +** n is the number of children to spawn (defaults to 2 * N_PROCS) +*/ + +USERMAIN( main ) { + int count = 2 * N_PROCS; // number of children to spawn + char ch = 'j'; // default character to print + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userJ: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + write( CHAN_SIO, &ch, 1 ); + + // set up the command-line arguments + char *argsy[] = { "userY", "Y", "10", NULL }; + + for( int i = 0; i < count ; ++i ) { + int whom = spawn( ProgY, argsy ); + if( whom < 0 ) { + write( CHAN_SIO, "!j!", 3 ); + } else { + write( CHAN_SIO, &ch, 1 ); + } + } + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progKL.c b/user/progKL.c new file mode 100644 index 0000000..6bfb987 --- /dev/null +++ b/user/progKL.c @@ -0,0 +1,61 @@ +#include + +/** +** User function main #4: exit, fork, exec, sleep, write +** +** Loops, spawning N copies of userX and sleeping between spawns. +** +** Invoked as: main4 x n +** where x is the ID character +** n is the iteration count (defaults to 5) +*/ + +USERMAIN( main ) { + int count = 5; // default iteration count + char ch = '4'; // default character to print + int nap = 30; // nap time + char msg2[] = "*4*"; // "error" message to print + char buf[32]; + + // process the command-line arguments + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "main4: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + write( CHAN_SIO, &ch, 1 ); + + // argument vector for the processes we will spawn + char *arglist[] = { "userX", "X", buf, NULL }; + + for( int i = 0; i < count ; ++i ) { + + write( CHAN_SIO, &ch, 1 ); + + // second argument to X is 100 plus the iteration number + sprint( buf, "%d", 100 + i ); + int whom = spawn( ProgX, arglist ); + if( whom < 0 ) { + swrites( msg2 ); + } else { + write( CHAN_SIO, &ch, 1 ); + } + + sleep( SEC_TO_MS(nap) ); + } + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progMN.c b/user/progMN.c new file mode 100644 index 0000000..38ccd31 --- /dev/null +++ b/user/progMN.c @@ -0,0 +1,72 @@ +#include + +/** +** User function main #5: exit, fork, exec, write +** +** Iterates spawning copies of userW (and possibly userZ), reporting +** their PIDs as it goes. +** +** Invoked as: main5 x n b +** where x is the ID character +** n is the iteration count +** b is the w&z boolean +*/ + +USERMAIN( main ) { + int count = 5; // default iteration count + char ch = '5'; // default character to print + int alsoZ = 0; // also do userZ? + char msgw[] = "*5w*"; + char msgz[] = "*5z*"; + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 4: alsoZ = argv[3][0] == 't'; + // FALL THROUGH + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "main5: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // update the extra message strings + msgw[1] = msgz[1] = ch; + + // announce our presence + write( CHAN_SIO, &ch, 1 ); + + // set up the argument vector(s) + + // W: 15 iterations, 5-second sleep + char *argsw[] = { "userW", "W", "15", "5", NULL }; + + // Z: 15 iterations + char *argsz[] = { "userZ", "Z", "15", NULL }; + + for( int i = 0; i < count; ++i ) { + write( CHAN_SIO, &ch, 1 ); + int whom = spawn( ProgW, argsw ); + if( whom < 1 ) { + swrites( msgw ); + } + if( alsoZ ) { + whom = spawn( ProgZ, argsz ); + if( whom < 1 ) { + swrites( msgz ); + } + } + } + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progP.c b/user/progP.c new file mode 100644 index 0000000..5a264a5 --- /dev/null +++ b/user/progP.c @@ -0,0 +1,51 @@ +#include "common.h" + +/** +** User function P: exit, sleep, write, gettime +** +** Reports itself, then loops reporting itself +** +** Invoked as: userP x [ n [ t ] ] +** where x is the ID character +** n is the iteration count (defaults to 3) +** t is the sleep time (defaults to 2 seconds) +*/ + +USERMAIN( main ) { + int count = 3; // default iteration count + char ch = 'p'; // default character to print + int nap = 2; // nap time + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 4: nap = str2int( argv[3], 10 ); + // FALL THROUGH + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userP: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + uint32_t now = gettime(); + sprint( buf, " P@%u", now ); + swrites( buf ); + + for( int i = 0; i < count; ++i ) { + sleep( SEC_TO_MS(nap) ); + write( CHAN_SIO, &ch, 1 ); + } + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progQ.c b/user/progQ.c new file mode 100644 index 0000000..ecfcffc --- /dev/null +++ b/user/progQ.c @@ -0,0 +1,43 @@ +#include + +/** +** User function Q: exit, write, bogus +** +** Reports itself, then tries to execute a bogus system call +** +** Invoked as: userQ x +** where x is the ID character +*/ + +USERMAIN( main ) { + char ch = 'q'; // default character to print + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userQ: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + write( CHAN_SIO, &ch, 1 ); + + // try something weird + bogus(); + + // should not have come back here! + sprint( buf, "!!!!! %c returned from bogus syscall!?!?!\n", ch ); + cwrites( buf ); + + exit( 1 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progR.c b/user/progR.c new file mode 100644 index 0000000..1d47f6b --- /dev/null +++ b/user/progR.c @@ -0,0 +1,99 @@ +#include + +/** +** User function R: exit, sleep, write, fork, getpid, getppid, +** +** Reports itself and its sequence number, along with its PID and +** its parent's PID. It then delays, forks, delays, reports again, +** and exits. +** +** Invoked as: userR x n [ s ] +** where x is the ID character +** n is the sequence number of the initial incarnation +** s is the initial delay time (defaults to 10) +*/ + +USERMAIN( main ) { + char ch = 'r'; // default character to print + int delay = 10; // initial delay count + int seq = 99; // my sequence number + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 4: delay = str2int( argv[3], 10 ); + // FALL THROUGH + case 3: seq = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userR: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + /* + ** C oddity: a label cannot immediately precede a declaration. + ** + ** Declarations are not considered "statements" in C. Prior to + ** C99, all declarations had to precede any statements inside a + ** block. Labels can only appear before statements. C99 allowed + ** the mixing of declarations and statements, but did not relax + ** the requirement that labels precede only statements. + ** + ** That's why the declarations of these variables occur before the + ** label, but their initializations occur after the label. + ** + ** As the PSA says on TV, "The more you know..." :-) + */ + + int32_t pid; + int32_t ppid; + + restart: + + // announce our presence + pid = getpid(); + ppid = getppid(); + + sprint( buf, " %c[%d,%d,%d]", ch, seq, pid, ppid ); + swrites( buf ); + + sleep( SEC_TO_MS(delay) ); + + // create the next child in sequence + if( seq < 5 ) { + ++seq; + int32_t n = fork(); + switch( n ) { + case -1: + // failure? + sprint( buf, "** R[%d] fork code %d\n", pid, n ); + cwrites( buf ); + break; + case 0: + // child + goto restart; + default: + // parent + --seq; + sleep( SEC_TO_MS(delay) ); + } + } + + // final report - PPID may change, but PID and seq shouldn't + pid = getpid(); + ppid = getppid(); + sprint( buf, " %c[%d,%d,%d]", ch, seq, pid, ppid ); + swrites( buf ); + + exit( 0 ); + + return( 42 ); // shut the compiler up! + +} diff --git a/user/progS.c b/user/progS.c new file mode 100644 index 0000000..d220955 --- /dev/null +++ b/user/progS.c @@ -0,0 +1,50 @@ +#include + +/** +** User function S: exit, sleep, write +** +** Reports itself, then loops forever, sleeping on each iteration +** +** Invoked as: userS x [ s ] +** where x is the ID character +** s is the sleep time (defaults to 20) +*/ + +USERMAIN( main ) { + char ch = 's'; // default character to print + int nap = 20; // nap time + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 3: nap = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userS: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + write( CHAN_SIO, &ch, 1 ); + + sprint( buf, "userS sleeping %d(%d)\n", nap, SEC_TO_MS(nap) ); + cwrites( buf ); + + for(;;) { + sleep( SEC_TO_MS(nap) ); + write( CHAN_SIO, &ch, 1 ); + } + + sprint( buf, "!! %c exiting!?!?!?\n", ch ); + cwrites( buf ); + exit( 1 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progTUV.c b/user/progTUV.c new file mode 100644 index 0000000..3d5ed49 --- /dev/null +++ b/user/progTUV.c @@ -0,0 +1,169 @@ +#include + +/** +** User function main #6: exit, fork, exec, kill, waitpid, sleep, write +** +** Reports, then loops spawing userW, sleeps, then waits for or kills +** all its children. +** +** Invoked as: main6 x c b +** where x is the ID character +** c is the child count +** b is wait/kill indicator ('w', 'W', or 'k') +*/ + +#ifndef MAX_CHILDREN +#define MAX_CHILDREN 50 +#endif + +USERMAIN( main ) { + int count = 3; // default child count + char ch = '6'; // default character to print + int nap = 8; // nap time + bool_t waiting = true; // default is waiting by PID + bool_t bypid = true; + char buf[128]; + uint_t children[MAX_CHILDREN]; + int nkids = 0; + char ch2[] = "*?*"; + + // process the command-line arguments + switch( argc ) { + case 4: waiting = argv[3][0] != 'k'; // 'w'/'W' -> wait, else -> kill + bypid = argv[3][0] != 'w'; // 'W'/'k' -> by PID + // FALL THROUGH + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "main6: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // fix the secondary output message (for indicating errors) + ch2[1] = ch; + + // announce our presence + write( CHAN_SIO, &ch, 1 ); + + // set up the argument vector + char *argsw[] = { "userW", "W", "10", "5", NULL }; + + for( int i = 0; i < count; ++i ) { + int whom = spawn( ProgW, argsw ); + if( whom < 0 ) { + swrites( ch2 ); + } else { + children[nkids++] = whom; + } + } + + // let the children start + sleep( SEC_TO_MS(nap) ); + + // collect exit status information + + // current child index + int n = 0; + + do { + int this; + int32_t status; + + // are we waiting for or killing it? + if( waiting ) { + this = waitpid( bypid ? children[n] : 0, &status ); + } else { + // always by PID + this = kill( children[n] ); + } + + // what was the result? + if( this < SUCCESS ) { + + // uh-oh - something went wrong + + // "no children" means we're all done + if( this != E_NO_CHILDREN ) { + if( waiting ) { + sprint( buf, "!! %c: waitpid(%d) status %d\n", + ch, bypid ? children[n] : 0, this ); + } else { + sprint( buf, "!! %c: kill(%d) status %d\n", + ch, children[n], this ); + } + } else { + sprint( buf, "!! %c: no children\n", ch ); + } + + // regardless, we're outta here + break; + + } else { + + // locate the child + int ix = -1; + + // were we looking by PID? + if( bypid ) { + // we should have just gotten the one we were looking for + if( this != children[n] ) { + // uh-oh + sprint( buf, "** %c: wait/kill PID %d, got %d\n", + ch, children[n], this ); + cwrites( buf ); + } else { + ix = n; + } + } + + // either not looking by PID, or the lookup failed somehow + if( ix < 0 ) { + int i; + for( i = 0; i < nkids; ++i ) { + if( children[i] == this ) { + ix = i; + break; + } + } + } + + // if ix == -1, the PID we received isn't in our list of children + + if( ix < 0 ) { + + // didn't find an entry for this PID??? + sprint( buf, "!! %c: child PID %d term, NOT FOUND\n", + ch, this ); + + } else { + + // found this PID in our list of children + if( ix != n ) { + // ... but it's out of sequence + sprint( buf, "== %c: child %d (%d,%d) status %d\n", + ch, ix, n, this, status ); + } else { + sprint( buf, "== %c: child %d (%d) status %d\n", + ch, ix, this, status ); + } + } + + } + + cwrites( buf ); + + ++n; + + } while( n < nkids ); + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progW.c b/user/progW.c new file mode 100644 index 0000000..5903663 --- /dev/null +++ b/user/progW.c @@ -0,0 +1,57 @@ +#include + +/** +** User function W: exit, sleep, write, getpid, gettime +** +** Reports its presence, then iterates 'n' times printing identifying +** information and sleeping, before exiting. +** +** Invoked as: userW x [ n [ s ] ] +** where x is the ID character +** n is the iteration count (defaults to 20) +** s is the sleep time (defaults to 3 seconds) +*/ + +USERMAIN( main ) { + int count = 20; // default iteration count + char ch = 'w'; // default character to print + int nap = 3; // nap length + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 4: nap = str2int( argv[3], 10 ); + // FALL THROUGH + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userW: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + int pid = getpid(); + uint32_t now = gettime(); + sprint( buf, " %c[%d,%u]", ch, pid, now ); + swrites( buf ); + + write( CHAN_SIO, &ch, 1 ); + + for( int i = 0; i < count ; ++i ) { + now = gettime(); + sprint( buf, " %c[%d,%u] ", ch, pid, now ); + swrites( buf ); + sleep( SEC_TO_MS(nap) ); + } + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progX.c b/user/progX.c new file mode 100644 index 0000000..ed356b9 --- /dev/null +++ b/user/progX.c @@ -0,0 +1,48 @@ +#include + +/** +** User function X: exit, write, getpid +** +** Prints its PID at start and exit, iterates printing its character +** N times, and exits with a status of 12. +** +** Invoked as: userX x n +** where x is the ID character +** n is the iteration count +*/ + +USERMAIN( main ) { + int count = 20; // iteration count + char ch = 'x'; // default character to print + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userX: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + int pid = getpid(); + sprint( buf, " %c[%d]", ch, pid ); + swrites( buf ); + + for( int i = 0; i < count ; ++i ) { + swrites( buf ); + DELAY(STD); + } + + exit( 12 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progY.c b/user/progY.c new file mode 100644 index 0000000..194f188 --- /dev/null +++ b/user/progY.c @@ -0,0 +1,49 @@ +#include + +/** +** User function Y: exit, sleep, write, getpid +** +** Reports its PID, then iterates N times printing 'Yx' and +** sleeping for one second, then exits. +** +** Invoked as: userY x [ n ] +** where x is the ID character +** n is the iteration count (defaults to 10) +*/ + +USERMAIN( main ) { + int count = 10; // default iteration count + char ch = 'y'; // default character to print + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "?: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // report our presence + int pid = getpid(); + sprint( buf, " %c[%d]", ch, pid ); + swrites( buf ); + + for( int i = 0; i < count ; ++i ) { + swrites( buf ); + DELAY(STD); + sleep( SEC_TO_MS(1) ); + } + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/progZ.c b/user/progZ.c new file mode 100644 index 0000000..cc394c4 --- /dev/null +++ b/user/progZ.c @@ -0,0 +1,57 @@ +#include + +/** +** User function Z: exit, sleep, write, getpid +** +** Prints its ID, then records PID and PPID, loops printing its ID, +** and finally re-gets PPID for comparison. Yields after every second +** ID print in the loop. +** +** This code is used as a handy "spawn me" test routine; it is spawned +** by several of the standard test processes. +** +** Invoked as: userZ x [ n ] +** where x is the ID character +** n is the iteration count (defaults to 10) +*/ + +USERMAIN( main ) { + int count = 10; // default iteration count + char ch = 'z'; // default character to print + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "?: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // announce our presence + int pid = getpid(); + sprint( buf, " %c[%d]", ch, pid ); + swrites( buf ); + + // iterate for a while; occasionally yield the CPU + for( int i = 0; i < count ; ++i ) { + sprint( buf, " %c[%d]", ch, i ); + swrites( buf ); + DELAY(STD); + if( i & 1 ) { + sleep( 0 ); + } + } + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} diff --git a/user/shell.c b/user/shell.c new file mode 100644 index 0000000..5412033 --- /dev/null +++ b/user/shell.c @@ -0,0 +1,343 @@ +#include + +// should we keep going? +static bool_t time_to_stop = false; + +// number of spawned but uncollected children +static int children = 0; + +/* +** For the test programs in the baseline system, command-line arguments +** follow these rules. The first two entries are as follows: +** +** argv[0] the name used to "invoke" this process +** argv[1] the "character to print" (identifies the process) +** +** Most user programs have one or more additional arguments. +** +** See the comment at the beginning of each user-code source file for +** information on the argument list that code expects. +*/ + +/* +** "Spawn table" process entry. Similar to that in init.c, +** except this one has no place to store the PID of the child. +*/ +typedef struct proc_s { + uint_t index; // process table index + int8_t prio; // process priority + char select[3]; // identifying character, NUL, extra + char *args[MAX_ARGS]; // argument vector strings +} proc_t; + +/* +** Create a spawn table entry for a process with a string literal +** as its argument buffer. We rely on the fact that the C standard +** ensures our array of pointers will be filled out with NULLs +*/ +#define PROCENT(e, p, s, ...) { e, p, s, { __VA_ARGS__ , NULL } } + +// sentinel value for the end of the table - must be updated +// if you have more than 90,210 user programs in the table +#define TBLEND 90210 + +/* +** The spawn table contains entries for processes that are started +** by the shell. +*/ +static proc_t spawn_table[] = { + + // Users A-C each run ProgABC, which loops printing its character +#if defined(SPAWN_A) + PROCENT( ProgABC, PRIO_STD, "A", "userA", "A", "30" ), +#endif +#if defined(SPAWN_B) + PROCENT( ProgABC, PRIO_STD, "B", "userB", "B", "30" ), +#endif +#if defined(SPAWN_C) + PROCENT( ProgABC, PRIO_STD, "C", "userC", "C", "30" ), +#endif + + // Users D and E run ProgDE, which is like ProgABC but doesn't exit() +#if defined(SPAWN_D) + PROCENT( ProgDE, PRIO_STD, "D", "userD", "D", "20" ), +#endif +#if defined(SPAWN_E) + PROCENT( ProgDE, PRIO_STD, "E", "userE", "E", "20" ), +#endif + + // Users F and G run ProgFG, which sleeps between write() calls +#if defined(SPAWN_F) + PROCENT( ProgFG, PRIO_STD, "F", "userF", "F", "20" ), +#endif +#if defined(SPAWN_G) + PROCENT( ProgFG, PRIO_STD, "G", "userG", "G", "10" ), +#endif + + // User H tests reparenting of orphaned children +#if defined(SPAWN_H) + PROCENT( ProgH, PRIO_STD, "H", "userH", "H", "4" ), +#endif + + // User I spawns several children, kills one, and waits for all +#if defined(SPAWN_I) + PROCENT( ProgI, PRIO_STD, "I", "userI", "I" ), +#endif + + // User J tries to spawn 2 * N_PROCS children +#if defined(SPAWN_J) + PROCENT( ProgJ, PRIO_STD, "J", "userJ", "J" ), +#endif + + // Users K and L iterate spawning userX and sleeping +#if defined(SPAWN_K) + PROCENT( ProgKL, PRIO_STD, "K", "userK", "K", "8" ), +#endif +#if defined(SPAWN_L) + PROCENT( ProgKL, PRIO_STD, "L", "userL", "L", "5" ), +#endif + + // Users M and N spawn copies of userW and userZ via ProgMN +#if defined(SPAWN_M) + PROCENT( ProgMN, PRIO_STD, "M", "userM", "M", "5", "f" ), +#endif +#if defined(SPAWN_N) + PROCENT( ProgMN, PRIO_STD, "N", "userN", "N", "5", "t" ), +#endif + + // There is no user O + + // User P iterates, reporting system time and stats, and sleeping +#if defined(SPAWN_P) + PROCENT( ProgP, PRIO_STD, "P", "userP", "P", "3", "2" ), +#endif + + // User Q tries to execute a bad system call +#if defined(SPAWN_Q) + PROCENT( ProgQ, PRIO_STD, "Q", "userQ", "Q" ), +#endif + + // User R reports its PID, PPID, and sequence number; it + // calls fork() but not exec(), with each child getting the + // next sequence number, to a total of five copies +#if defined(SPAWN_R) + PROCENT( ProgR, PRIO_STD, "R", "userR", "R", "20", "1" ), +#endif + + // User S loops forever, sleeping 13 sec. on each iteration +#if defined(SPAWN_S) + PROCENT( ProgS, PRIO_STD, "S", "userS", "S", "13" ), +#endif + + // Users T-V run ProgTUV(); they spawn copies of userW + // User T waits for any child + // User U waits for each child by PID + // User V kills each child +#if defined(SPAWN_T) + PROCENT( ProgTUV, PRIO_STD, "T", "userT", "T", "6", "w" ), +#endif +#if defined(SPAWN_U) + PROCENT( ProgTUV, PRIO_STD, "U", "userU", "U", "6", "W" ), +#endif +#if defined(SPAWN_V) + PROCENT( ProgTUV, PRIO_STD, "V", "userV", "V", "6", "k" ), +#endif + + // a dummy entry to use as a sentinel + { TBLEND } + + // these processes are spawned by the ones above, and are never + // spawned directly. + + // PROCENT( ProgW, PRIO_STD, "?", "userW", "W", "20", "3" ), + // PROCENT( ProgX, PRIO_STD, "?", "userX", "X", "20" ), + // PROCENT( ProgY, PRIO_STD, "?", "userY", "Y", "10" ), + // PROCENT( ProgZ, PRIO_STD, "?", "userZ", "Z", "10" ) +}; + +/* +** usage function +*/ +static void usage( void ) { + swrites( "\nTests - run with '@x', where 'x' is one or more of:\n " ); + proc_t *p = spawn_table; + while( p->index != TBLEND ) { + swritech( ' ' ); + swritech( p->select[0] ); + } + swrites( "\nOther commands: @* (all), @h (help), @x (exit)\n" ); +} + +/* +** run a program from the program table, or a builtin command +*/ +static int run( char which ) { + char buf[128]; + register proc_t *p; + + if( which == 'h' ) { + + // builtin "help" command + usage(); + + } else if( which == 'x' ) { + + // builtin "exit" command + time_to_stop = true; + + } else if( which == '*' ) { + + // torture test! run everything! + for( p = spawn_table; p->index != TBLEND; ++p ) { + int status = spawn( p->index, p->args ); + if( status > 0 ) { + ++children; + } + } + + } else { + + // must be a single test; find and run it + for( p = spawn_table; p->index != TBLEND; ++p ) { + if( p->select[0] == which ) { + // found it! + int status = spawn( p->index, p->args ); + if( status > 0 ) { + ++children; + } + return status; + } + } + + // uh-oh, made it through the table without finding the program + sprint( buf, "shell: unknown cmd '%c'\n", which ); + swrites( buf ); + usage(); + } + + return 0; +} + +/** +** edit - perform any command-line editing we need to do +** +** @param line Input line buffer +** @param n Number of valid bytes in the buffer +*/ +static int edit( char line[], int n ) { + char *ptr = line + n - 1; // last char in buffer + + // strip the EOLN sequence + while( n > 0 ) { + if( *ptr == '\n' || *ptr == '\r' ) { + --n; + } else { + break; + } + } + + // add a trailing NUL byte + if( n > 0 ) { + line[n] = '\0'; + } + + return n; +} + +/** +** shell - extremely simple shell for spawning test programs +** +** Scheduled by _kshell() when the character 'u' is typed on +** the console keyboard. +*/ +USERMAIN( main ) { + + // keep the compiler happy + (void) argc; + (void) argv; + + // report that we're up and running + swrites( "Shell is ready\n" ); + + // print a summary of the commands we'll accept + usage(); + + // loop forever + while( !time_to_stop ) { + char line[128]; + char *ptr; + + // the shell reads one line from the keyboard, parses it, + // and performs whatever command it requests. + + swrites( "\n> " ); + int n = read( CHAN_SIO, line, sizeof(line) ); + + // shortest valid command is "@?", so must have 3+ chars here + if( n < 3 ) { + // ignore it + continue; + } + + // edit it as needed; new shortest command is 2+ chars + if( (n=edit(line,n)) < 2 ) { + continue; + } + + // find the '@' + int i = 0; + for( ptr = line; i < n; ++i, ++ptr ) { + if( *ptr == '@' ) { + break; + } + } + + // did we find an '@'? + if( i < n ) { + + // yes; process any commands that follow it + ++ptr; + + for( ; *ptr != '\0'; ++ptr ) { + char buf[128]; + int pid = run( *ptr ); + + if( pid < 0 ) { + // spawn() failed + sprint( buf, "+++ Shell spawn %c failed, code %d\n", + *ptr, pid ); + cwrites( buf ); + } + + // should we end it all? + if( time_to_stop ) { + break; + } + } // for + + // now, wait for all the spawned children + while( children > 0 ) { + // wait for the child + int32_t status; + char buf[128]; + int whom = waitpid( 0, &status ); + + // figure out the result + if( whom == E_NO_CHILDREN ) { + break; + } else if( whom < 1 ) { + sprint( buf, "shell: waitpid() returned %d\n", whom ); + } else { + --children; + sprint( buf, "shell: PID %d exit status %d\n", + whom, status ); + } + // report it + swrites( buf ); + } + } // if i < n + } // while + + cwrites( "!!! shell exited loop???\n" ); + exit( 1 ); +} diff --git a/user/user.ld b/user/user.ld new file mode 100644 index 0000000..9e31dff --- /dev/null +++ b/user/user.ld @@ -0,0 +1,51 @@ +/* +** Simple linker script for user-level programs. +*/ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) + +SECTIONS +{ + /* user text begins at the second page of the address space */ + . = 0x1000; + + .text : { + KEEP(*(.text .stub .text.* .gnu.linkonce.t.*)) + } + + /* define some standard symbols */ + PROVIDE(etext = .); + PROVIDE(_etext = .); + + /* read-only data will go at the end of the text section */ + .rodata : { + KEEP(*(.rodata .rodata.* .gnu.linkonce.r.*)) + } + + /* Align the data segment at the next page boundary */ + . = ALIGN(0x1000); + + .data : { + KEEP(*(.data)) + } + + PROVIDE(edata = .); + PROVIDE(_edata = .); + + /* Page-align the BSS segment */ + . = ALIGN(0x1000); + + PROVIDE(__bss_start = .); + + .bss : { + KEEP(*(.bss)) + } + + PROVIDE(_end = .); + + /DISCARD/ : { + *(.stab .stab_info .stabstr .eh_frame .note.GNU-stack .note.gnu.property .comment) + } +} diff --git a/util/BuildImage.c b/util/BuildImage.c new file mode 100644 index 0000000..2124c9d --- /dev/null +++ b/util/BuildImage.c @@ -0,0 +1,415 @@ +/** +** SCCS ID: @(#)BuildImage.c 2.2 1/16/25 +** +** @file BuildImage.c +** +** @author K. Reek +** @author Jon Coles +** @author Warren R. Carithers +** @author Garrett C. Smith +** +** Modify the bootstrap image to include the information +** on the programs to be loaded, and produce the file +** that contains the concatenation of these programs. +** +*/ + +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 + +#define DRIVE_FLOPPY 0x00 +#define DRIVE_USB 0x80 + +#define SECT_SIZE 512 + +char *progname; /* invocation name of this program */ +char *bootstrap_filename; /* path of file holding bootstrap program */ +char *output_filename; /* path of disk image file */ +FILE *out; /* output stream for disk image file */ +short drive = DRIVE_USB; /* boot drive */ + +/* +** Array into which program information will be stored, starting at the +** end and moving back toward the front. The array is the same size as +** a sector, which is guaranteed to be larger than the maximum possible +** space available for this stuff in the bootstrap image. Thus, the +** bootstrap image itself (and the amount of space available on the +** device) are the only limiting factors on how many program sections +** can be loaded. +*/ + +#define N_INFO ( SECT_SIZE / sizeof( short ) ) + +short info[ N_INFO ]; +int n_info = N_INFO; + +/** +** quit with an appropriate message +** +** @param msg NULL, or a message to be printed to stderr +** @param call_perror non-zero if perror() should be used; else, +** fprintf() will be used +** +** does not return +*/ +void quit( char *msg, int call_perror ) { + if( msg != NULL ){ + // preserve the error code in case we need it + int err_num = errno; + fprintf( stderr, "%s: ", progname ); + errno = err_num; + if( call_perror ){ + perror( msg ); + } else { + fprintf( stderr, "%s\n", msg ); + } + } + if( output_filename != NULL ){ + unlink( output_filename ); + } + exit( EXIT_FAILURE ); + // NOTREACHED +} + +const char usage_error_msg[] = + "\nUsage: %s [ -d drive ] -b bootfile -o outfile { progfile loadpt } ...\n\n" + "\t'drive' is either 'floppy' or 'usb' (default 'usb')\n\n" + "\tThere must be at least one program file and load point.\n\n" + "\tLoad points may be specified either as 32-bit quantities in hex,\n" + "\tdecimal or octal (e.g. 0x10c00, 68608, 0206000 are all equivalent),\n" + "\tor as an explicit segment:offset pair whose digits are always\n" + "\tinterpreted as hexadecimal values (e.g. 10c0:0000, 1000:0c00 are\n" + "\tboth equivalent to the previous examples).\n\n"; + +/** +** print a usage message and then call quit() +** +** does not return +*/ +void usage_error( void ){ + fprintf( stderr, usage_error_msg, progname ); + quit( NULL, FALSE ); + // NOTREACHED +} + +/** +** copy the contents of a binary file into the output file, padding the +** last sector with NUL bytes +** +** @param in open FILE to be read +** @return the number of sectors copied from the file +*/ +int copy_file( FILE *in ){ + int n_sectors = 0; + char buf[ SECT_SIZE ]; + int n_bytes; + int i; + + /* + ** Copy the file to the output, being careful that the + ** last sector is padded with null bytes out to the + ** sector size. + */ + n_sectors = 0; + while( (n_bytes = fread( buf, 1, sizeof( buf ), in )) > 0 ){ + // pad this sector out to block size + if( n_bytes < sizeof( buf ) ){ + int i; + + for( i = n_bytes; i < sizeof( buf ); i += 1 ){ + buf[ i ] = '\0'; + } + } + if( fwrite( buf, 1, sizeof( buf ), out ) != sizeof( buf ) ){ + quit( "Write failed or was wrong size", FALSE ); + } + n_sectors += 1; + } + return n_sectors; +} + +/** +** process a file whose contents should be at a specific' +** address in memory when the program is loaded +** +** @param name path to the file to be copied +** @param addr string containing the load address +*/ +void process_file( char *name, char *addr ){ + long address; + short segment, offset; + int n_bytes; + + /* + ** Open the input file. + */ + FILE *in = fopen( name, "rb" ); + if( in == NULL ){ + quit( name, TRUE ); + } + + /* + ** Copy the file to the output, being careful that the + ** last block is padded with null bytes. + */ + int n_sectors = copy_file( in ); + fclose( in ); + + /* + ** Decode the address they gave us. We'll accept two forms: + ** "nnnn:nnnn" for a segment:offset value (assumed to be hex), + ** "nnnnnnn" for a decimal, hex, or octal value + */ + int valid_address = FALSE; + char *cp = strchr( addr, ':' ); + if( cp != NULL ){ + // must be in nnnn:nnnn form exactly + if( strlen( addr ) == 9 && cp == addr + 4 ){ + char *ep1, *ep2; + int a1, a2; + + segment = strtol( addr, &ep1, 16 ); + offset = strtol( addr + 5, &ep2, 16 ); + address = ( segment << 4 ) + offset; + valid_address = *ep1 == '\0' && *ep2 == '\0'; + } else { + fprintf( stderr, "Bad address format - '%s'\n", addr ); + quit( NULL, FALSE ); + } + } else { + // just a number, possibly hex or octal + char *ep; + + address = strtol( addr, &ep, 0 ); + segment = (short)( address >> 4 ); + offset = (short)( address & 0xf ); + valid_address = *ep == '\0' && address <= 0x0009ffff; + } + + if( !valid_address ){ + fprintf( stderr, "%s: Invalid address: %s\n", progname, addr ); + quit( NULL, FALSE ); + } + + /* + ** Make sure the program will fit! + */ + if( address + n_sectors * SECT_SIZE > 0x0009ffff ){ + fprintf( stderr, "Program %s too large to start at 0x%08x\n", + name, (unsigned int) address ); + quit( NULL, FALSE ); + } + + if( n_info < 3 ){ + quit( "Too many programs!", FALSE ); + } + + + /* + ** Looks good: report and store the information. + */ + fprintf( stderr, " %s: %d sectors, loaded at 0x%x\n", + name, n_sectors, (unsigned int) address ); + + info[ --n_info ] = n_sectors; + info[ --n_info ] = segment; + info[ --n_info ] = offset; +} + +/* +** Global variables set by getopt() +*/ + +extern int optind, optopt; +extern char *optarg; + +/** +** process the command-line arguments +** +** @param ac the count of entries in av +** @param av the argument vector +*/ +void process_args( int ac, char **av ) { + int c; + + while( (c=getopt(ac,av,":d:o:b:")) != EOF ) { + + switch( c ) { + + case ':': /* missing arg value */ + fprintf( stderr, "missing operand after -%c\n", optopt ); + /* FALL THROUGH */ + + case '?': /* error */ + usage_error(); + /* NOTREACHED */ + + case 'b': /* -b bootstrap_file */ + bootstrap_filename = optarg; + break; + + case 'd': /* -d drive */ + switch( *optarg ) { + case 'f': drive = DRIVE_FLOPPY; break; + case 'u': drive = DRIVE_USB; break; + default: usage_error(); + } + break; + + case 'o': /* -o output_file */ + output_filename = optarg; + break; + + default: + usage_error(); + + } + + } + + if( !bootstrap_filename ) { + fprintf( stderr, "%s: no bootstrap file specified\n", progname ); + exit( 2 ); + } + + if( !output_filename ) { + fprintf( stderr, "%s: no disk image file specified\n", progname ); + exit( 2 ); + } + + /* + ** Must have at least two remaining arguments (file to load, + ** address at which it should be loaded), and must have an + ** even number of remaining arguments. + */ + int remain = ac - optind; + if( remain < 2 || (remain & 1) != 0 ) { + usage_error(); + } + +} + +/** +** build a bootable image file from one or more binary files +** +** usage: +** BuildImage [ -d drive ] -b bootfile -o outfile { binfile1 loadpt1 } ... ] +** +** @param ac command-line argument count +** @param av command-line argument vector +** @return EXIT_SUCCESS or EXIT_FAILURE +*/ +int main( int ac, char **av ) { + FILE *bootimage; + int bootimage_size; + int n_bytes, n_words; + short existing_data[ N_INFO ]; + int i; + + /* + ** Save the program name for error messages + */ + progname = strrchr( av[ 0 ], '/' ); + if( progname != NULL ){ + progname++; + } else { + progname = av[ 0 ]; + } + + /* + ** Process arguments + */ + process_args( ac, av ); + + /* + ** Open the output file + */ + + out = fopen( output_filename, "wb+" ); + if( out == NULL ){ + quit( output_filename, TRUE ); + } + + /* + ** Open the bootstrap file and copy it to the output image. + */ + bootimage = fopen( bootstrap_filename, "rb" ); + if( bootimage == NULL ){ + quit( bootstrap_filename, TRUE ); + } + + /* + ** Remember the size of the bootstrap for later, as we + ** need to patch some things into it + */ + int n_sectors = copy_file( bootimage ); + fclose( bootimage ); + + bootimage_size = n_sectors * SECT_SIZE; + fprintf( stderr, " %s: %d sectors\n", bootstrap_filename, n_sectors ); + + /* + ** Process the programs one by one + */ + ac -= optind; + av += optind; + while( ac >= 2 ){ + process_file( av[ 0 ], av[ 1 ] ); + ac -= 2; av += 2; + } + + /* + ** Check for oddball leftover argument + */ + if( ac > 0 ){ + usage_error(); + } + + /* + ** Seek to where the array of module data must begin and read + ** what's already there. + */ + n_words = ( N_INFO - n_info ); + n_bytes = n_words * sizeof( info[ 0 ] ); + fseek( out, bootimage_size - n_bytes, SEEK_SET ); + if( fread( existing_data, sizeof(info[0]), n_words, out ) != n_words ){ + quit( "Read from boot image failed or was too short", FALSE ); + } + + /* + ** If that space is non-zero, we have a problem + */ + for( i = 0; i < n_words; i += 1 ){ + if( existing_data[ i ] != 0 ){ + quit( "Too many programs to load!", FALSE ); + } + } + + /* + ** We know that we're only overwriting zeros at the end of + ** the bootstrap image, so it is ok to go ahead and do it. + */ + fseek( out, bootimage_size - n_bytes, SEEK_SET ); + if( fwrite( info + n_info, sizeof( info[ 0 ] ), n_words, out ) != n_words ){ + quit( "Write to boot image failed or was too short", FALSE ); + } + + /* + ** Write the drive index to the image. + */ + fseek( out, 508, SEEK_SET ); + fwrite( (void *)&drive, sizeof(drive), 1, out ); + + fclose( out ); + + return EXIT_SUCCESS; + +} diff --git a/util/Make.mk b/util/Make.mk new file mode 100644 index 0000000..0f45625 --- /dev/null +++ b/util/Make.mk @@ -0,0 +1,59 @@ +# +# Makefile fragment for the utility programs +# +# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level +# directory, and this will be pulled in automatically. +# + +################### +# FILES SECTION # +################### + +UTIL_BIN := BuildImage Offsets mkblob listblob + +################### +# RULES SECTION # +################### + +# how to make everything +util: $(UTIL_BIN) + +# +# Special rules for creating the utility programs. These are required +# because we don't want to use the same options as for the standalone +# binaries - we want these to be compiled as "normal" programs. +# + +BuildImage: util/BuildImage.c + @mkdir -p $(@D) + $(CC) -std=c99 -ggdb -o BuildImage util/BuildImage.c + +mkblob: util/mkblob.c + @mkdir -p $(@D) + $(CC) -std=c99 -ggdb -o mkblob util/mkblob.c + +listblob: util/listblob.c + @mkdir -p $(@D) + $(CC) -std=c99 -ggdb -o listblob util/listblob.c + +# +# Offsets is compiled using -mx32 to force a 32-bit execution environment +# for a program that runs under a 64-bit operating system. This ensures +# that pointers and long ints are 32 bits rather than 64 bits, which is +# critical to correctly determining the size of types and byte offsets for +# fields in structs. We also compile with "-fno-builtin" to avoid signature +# clashes between declarations in our system and function declarations +# built into the C compiler. +# +# If compiled with the CPP macro CREATE_HEADER_FILE defined, Offsets +# accepts a command-line argument "-h". This causes it to write its +# output as a standard C header file into a file named "include/offsets.h" +# where it can be included into other source files (e.g., to provide +# sizes of structs in C and assembly, or to provide byte offsets into +# structures for use in assembly code). +# + +Offsets: util/Offsets.c + @mkdir -p $(@D) + $(CC) -mx32 -std=c99 $(INCLUDES) -fno-builtin \ + -o Offsets util/Offsets.c diff --git a/util/Offsets.c b/util/Offsets.c new file mode 100644 index 0000000..3cf5a46 --- /dev/null +++ b/util/Offsets.c @@ -0,0 +1,250 @@ +/* +** SCCS ID: @(#)Offsets.c 2.2 1/23/25 +** +** @file Offsets.c +** +** @author Warren R. Carithers +** +** Print byte offsets for fields in various structures. +** +** This program exists to simplify life. If/when fields in a structure +** are changed, this can be modified, recompiled and executed to come up with +** byte offsets for use in accessing structure fields from assembly language. +** It makes use of the C 'offsetof' macro (defined since C89). +** +** IMPORTANT NOTE: compiling this on a 64-bit architecture will yield +** incorrect results by default, as 64-bit GCC versions most often use +** the LP64 model (longs and pointers are 64 bits). Add the "-mx32" +** option to the compiler (compile for x86_64, but use 32-bit sizes), +** and make sure you have the 'libc6-dev-i386' package installed (for +** Ubuntu systems). +** +** WATCH FOR clashes with standard system functions; compile with the +** "-fno-builtin" option to avoid warnings about clashes with builtin +** function declarations. +** +** Writes to stdout. Output contains information about type sizes and +** byte offsets for fields within structures. If invoked with the -h +** option, the output takes the form of a standard C header file; +** otherwise, the information is printed in ordinary text form. +** +** If compiled with the CREATE_HEADER_FILE macro defined, when invoked +** with the -h option, writes the data directly into a file named +** "offsets.h". +*/ + +// make sure we get all the kernel stuff +#define KERNEL_SRC + +// include any of our headers that define data structures to be described +#include +#include + +// avoid complaints about NULL from stdio.h +#ifdef NULL +#undef NULL +#endif + +#include +#include +#include +#include + +/* +** We don't include because of conflicts with a time_t data +** type we may be defining; instead, we provide our own prototypes for +** ctime() and time(). +*/ + +extern char *ctime( const __time_t *timep ); +extern __time_t time( __time_t *tloc ); + +/* +** Header comment, including header guard +** +** No newline on the "Creation date" line, because ctime() +** puts a newline at the end of the string it produces. +*/ +char h_prefix[] = "/**\n" +"** @file\toffsets.h\n" +"**\n" +"** GENERATED AUTOMATICALLY - DO NOT EDIT\n" +"**\n" +"** Creation date: %s" +"**\n" +"** This header file contains C Preprocessor macros which expand\n" +"** into the byte offsets needed to reach fields within structs\n" +"** used in the baseline system. Should those struct declarations\n" +"** change, the Offsets program should be modified (if needed),\n" +"** recompiled, and re-run to recreate this file.\n" +"*/\n" +"\n" +"#ifndef OFFSETS_H_\n" +"#define OFFSETS_H_\n"; + +/* +** Header guard suffix +*/ +char h_suffix[] = "\n" +"#endif\n"; + +// are we generating the .h file? +int genheader = 0; + +// header file stream +FILE *hfile; + +// prefix for header file lines + +// produce a report line +void process( const char *sname, const char *field, size_t bytes ) { + if( genheader ) { + char name[64]; + sprintf( name, "%s_%s", sname, field ); + fprintf( hfile, "#define\t%-23s\t%u\n", name, bytes ); + } else { + printf( " %-10s %u\n", field, bytes ); + } +} + +#ifdef CREATE_HEADER_FILE +// dump out the header +void setheader( void ) { + // trigger output into the header file + genheader = 1; + + hfile = fopen( "offsets.h", "w" ); + if( hfile == NULL ) { + perror( "offsets.h" ); + exit( 1 ); + } + + __time_t t; + (void) time( &t ); + + fprintf( hfile, h_prefix, ctime(&t) ); +} +#endif /* CREATE_HEADER_FILE */ + +// introduce an "offsets" section for structs +void hsection( const char *name, const char *typename, size_t size ) { + if( genheader ) { + fprintf( hfile, "\n// %s structure\n\n", typename ); + process( "SZ", name, size ); + fputc( '\n', hfile ); + } else { + printf( "Offsets into %s (%u bytes):\n", typename, size ); + } +} + +// introduce a "sizes" section for types +void tsection( const char *name, const char *typename ) { + if( genheader ) { + fprintf( hfile, "\n// Sizes of %s types\n\n", typename ); + } else { + printf( "Sizes of %s types:\n", typename ); + } +} + +int main( int argc, char *argv[] ) { + + hfile = stdout; + + if( argc > 1 ) { +#ifdef CREATE_HEADER_FILE + // only accept one argument + if( argc == 2 ) { + // -h: produce an offsets.h header file + if( argv[1][0] == '-' && argv[1][1] == '-h' ) { + setheader(); + } + } else { + fprintf( stderr, "usage: %s [-h]\n", argv[0] ); + exit( 1 ); + } +#else + // we accept no arguments + fprintf( stderr, "usage: %s\n", argv[0] ); + exit( 1 ); +#endif /* CREATE_HEADER_FILE */ + } + + /* + ** Basic and simple/opaque types + */ + + tsection( "SZ", "basic" ); + process( "SZ", "char", sizeof(char) ); + process( "SZ", "short", sizeof(short) ); + process( "SZ", "int", sizeof(int) ); + process( "SZ", "long", sizeof(long) ); + process( "SZ", "long_long", sizeof(long long) ); + process( "SZ", "pointer", sizeof(void *) ); + fputc( '\n', hfile ); + + tsection( "SZ", "our" ); + process( "SZ", "int8_t", sizeof(int8_t) ); + process( "SZ", "uint8_t", sizeof(uint8_t) ); + process( "SZ", "int16_t", sizeof(int16_t) ); + process( "SZ", "uint16_t", sizeof(uint16_t) ); + process( "SZ", "int32_t", sizeof(int32_t) ); + process( "SZ", "uint32_t", sizeof(uint32_t) ); + process( "SZ", "int64_t", sizeof(int64_t) ); + process( "SZ", "uint64_t", sizeof(uint64_t) ); + process( "SZ", "bool_t", sizeof(bool_t) ); + fputc( '\n', hfile ); + + /* + ** Structured types whose fields we are describing + */ + + // add entries for each type here, as needed + + hsection( "CTX", "context_t", sizeof(context_t) ); + process( "CTX", "ss", offsetof(context_t,ss) ); + process( "CTX", "gs", offsetof(context_t,gs) ); + process( "CTX", "fs", offsetof(context_t,fs) ); + process( "CTX", "es", offsetof(context_t,es) ); + process( "CTX", "ds", offsetof(context_t,ds) ); + process( "CTX", "edi", offsetof(context_t,edi) ); + process( "CTX", "esi", offsetof(context_t,esi) ); + process( "CTX", "ebp", offsetof(context_t,ebp) ); + process( "CTX", "esp", offsetof(context_t,esp) ); + process( "CTX", "ebx", offsetof(context_t,ebx) ); + process( "CTX", "edx", offsetof(context_t,edx) ); + process( "CTX", "ecx", offsetof(context_t,ecx) ); + process( "CTX", "eax", offsetof(context_t,eax) ); + process( "CTX", "vector", offsetof(context_t,vector) ); + process( "CTX", "code", offsetof(context_t,code) ); + process( "CTX", "eip", offsetof(context_t,eip) ); + process( "CTX", "cs", offsetof(context_t,cs) ); + process( "CTX", "eflags", offsetof(context_t,eflags) ); + fputc( '\n', hfile ); + + hsection( "SCT", "section_t", sizeof(section_t) ); + process( "SCT", "length", offsetof(section_t,length) ); + process( "SCT", "addr", offsetof(section_t,addr) ); + fputc( '\n', hfile ); + + hsection( "PCB", "pcb_t", sizeof(pcb_t) ); + process( "PCB", "context", offsetof(pcb_t,context) ); + process( "PCB", "next", offsetof(pcb_t,next) ); + process( "PCB", "parent", offsetof(pcb_t,parent) ); + process( "PCB", "wakeup", offsetof(pcb_t,wakeup) ); + process( "PCB", "exit_status", offsetof(pcb_t,exit_status) ); + process( "PCB", "pdir", offsetof(pcb_t,pdir) ); + process( "PCB", "sects", offsetof(pcb_t,sects) ); + process( "PCB", "pid", offsetof(pcb_t,pid) ); + process( "PCB", "state", offsetof(pcb_t,state) ); + process( "PCB", "priority", offsetof(pcb_t,priority) ); + process( "PCB", "ticks", offsetof(pcb_t,ticks) ); + fputc( '\n', hfile ); + + // finish up the offsets.h file if we need to + if( genheader ) { + fputs( h_suffix, hfile ); + fclose( hfile ); + } + + return( 0 ); +} diff --git a/util/alternatives/Make.mk b/util/alternatives/Make.mk new file mode 100644 index 0000000..d5703e8 --- /dev/null +++ b/util/alternatives/Make.mk @@ -0,0 +1,56 @@ +# +# Makefile fragment for the utility programs +# +# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level +# directory, and this will be pulled in automatically. +# + +SUBDIRS += util + +################### +# RULES SECTION # +################### + +# how to make everything +util: $(BUILDDIR)/util/BuildImage $(BUILDDIR)/util/Offsets \ + $(BUILDDIR)/util/mkblob $(BUILDDIR)/util/listblob + +# +# Special rules for creating the utility programs. These are required +# because we don't want to use the same options as for the standalone +# binaries - we want these to be compiled as "normal" programs. +# + +$(BUILDDIR)/util/BuildImage: util/BuildImage.c + @mkdir -p $(@D) + $(CC) -std=c99 -o $(BUILDDIR)/util/BuildImage util/BuildImage.c + +$(BUILDDIR)/util/mkblob: util/mkblob.c + @mkdir -p $(@D) + $(CC) -std=c99 -o $(BUILDDIR)/util/mkblob util/mkblob.c + +$(BUILDDIR)/util/listblob: util/listblob.c + @mkdir -p $(@D) + $(CC) -std=c99 -o $(BUILDDIR)/util/listblob util/listblob.c + +# +# Offsets is compiled using -mx32 to force a 32-bit execution environment +# for a program that runs under a 64-bit operating system. This ensures +# that pointers and long ints are 32 bits rather than 64 bits, which is +# critical to correctly determining the size of types and byte offsets for +# fields in structs. We also compile with "-fno-builtin" to avoid signature +# clashes between declarations in our system and function declarations +# built into the C compiler. +# +# If compiled with the CPP macro CREATE_HEADER_FILE defined, Offsets +# accepts a command-line argument "-h". This causes it to write its +# output as a standard C header file into a file named "include/offsets.h" +# where it can be included into other source files (e.g., to provide +# sizes of structs in C and assembly, or to provide byte offsets into +# structures for use in assembly code). +# + +$(BUILDDIR)/util/Offsets: util/Offsets.c + @mkdir -p $(@D) + $(CC) -mx32 -std=c99 $(INCLUDES) -fno-builtin \ + -o $(BUILDDIR)/util/Offsets util/Offsets.c diff --git a/util/alternatives/README b/util/alternatives/README new file mode 100644 index 0000000..ae4dfbe --- /dev/null +++ b/util/alternatives/README @@ -0,0 +1,31 @@ +This directory contains "alternative" versions of some pieces of the system. + +Things included here: + + Make.mk + This version of the Makefile fragment puts the utility programs + in build/util instead of in the top-level directory. + + kmem.c + A version of the memory allocator that works with blocks of memory + that aren't exactly one page in length. During initialilzation, it + just adds each memory region identified during the boot process by + calls to the BIOS; as pages are requested, they are carved out of + these large blocks. The freelist is ordered by starting block + address, and allocation uses a first-fit strateby. + + The allocation function has this prototype: + + void *km_page_alloc( unsigned int count ); + + This allows the allocation of multiple contiguous pages. As pages + are freed, they are merged back into the freelist, and adjacent + free pages are coalesced into single, larger blocks. + + lib.c + This file pulls in all the individual .c files for the common + library functions in the lib/ directory. It is intended as an + alternative to having the libk.a archive file for the kernel; + instead of linking against that library, the lib.o file can + just be provided to the linker when the kernel is created, + and all the common library functions will be available. diff --git a/util/alternatives/kmem.c b/util/alternatives/kmem.c new file mode 100644 index 0000000..f1abf02 --- /dev/null +++ b/util/alternatives/kmem.c @@ -0,0 +1,749 @@ +/** +** @file kmem.c +** +** @author Warren R. Carithers +** @author Kenneth Reek +** @author 4003-506 class of 20013 +** +** @brief Functions to perform dynamic memory allocation in the OS. +** +** NOTE: these should NOT be called by user processes! +** +** This allocator functions as a simple "slab" allocator; it allows +** allocation of either 4096-byte ("page") or 1024-byte ("slice") +** chunks of memory from the free pool. The free pool is initialized +** using the memory map provided by the BIOS during the boot sequence, +** and contains a series of blocks which are multiples of 4K bytes and +** which are aligned at 4K boundaries; they are held in the free list +** in order by base address. +** +** The "page" allocator allows allocation of one or more 4K blocks +** at a time. Requests are made for a specific number of 4K pages; +** the allocator locates the first free list entry that contains at +** least the requested amount of space. If that entry is the exact +** size requested, it is unlinked and returned; otherwise, the entry +** is split into a chunk of the requested size and the remainder. +** The chunk is returned, and the remainder replaces the original +** block in the free list. On deallocation, the block is inserted +** at the appropriate place in the free list, and physically adjacent +** blocks are coalesced into single, larger blocks. If a multi-page +** block is allocated, it should be deallocated one page at a time, +** because there is no record of the size of the original allocation - +** all we know is that it is N*4K bytes in length, so it's up to the +** requesting code to figure this out. +** +** The "slice" allocator operates by taking blocks from the "page" +** allocator and splitting them into four 1K slices, which it then +** manages. Requests are made for slices one at a time. If the free +** list contains an available slice, it is unlinked and returned; +** otherwise, a page is requested from the page allocator, split into +** slices, and the slices are added to the free list, after which the +** first one is returned. The slice free list is a simple linked list +** of these 1K blocks; because they are all the same size, no ordering +** is done on the free list, and no coalescing is performed. +** +*/ + +#define KERNEL_SRC + +#include + +// all other framework includes are next +#include + +#include +#include +#include +#include + +#include + +/* +** PRIVATE DEFINITIONS +*/ + +// parameters related to word and block sizes + +#define WORD_SIZE sizeof(int) +#define LOG2_OF_WORD_SIZE 2 + +#define LOG2_OF_PAGE_SIZE 12 + +#define LOG2_OF_SLICE_SIZE 10 + +// converters: pages to bytes, bytes to pages + +#define P2B(x) ((x) << LOG2_OF_PAGE_SIZE) +#define B2P(x) ((x) >> LOG2_OF_PAGE_SIZE) + +/* +** Name: adjacent +** +** Arguments: addresses of two blocks +** +** Description: Determines whether the second block immediately +** follows the first one. +*/ +#define adjacent(first,second) \ + ( (void *) (first) + P2B((first)->pages) == (void *) (second) ) + +/* +** PRIVATE DATA TYPES +*/ + +/* +** This structure keeps track of a single block of memory. All blocks +** are multiples of the base size (currently, 4KB). +*/ + +typedef struct block_s { + uint32_t pages; // length of this block, in pages + struct block_s *next; // pointer to the next free block +} block_t; + +/* +** Memory region information returned by the BIOS +** +** This data consists of a 32-bit integer followed +** by an array of region descriptor structures. +*/ + +// a handy union for playing with 64-bit addresses +typedef union b64_u { + uint32_t part[2]; + uint64_t all; +} b64_t; + +// the halves of a 64-bit address +#define LOW part[0] +#define HIGH part[1] + +// memory region descriptor +typedef struct memregion_s { + b64_t base; // base address + b64_t length; // region length + uint32_t type; // type of region + uint32_t acpi; // ACPI 3.0 info +} __attribute__((packed)) region_t; + +/* +** Region types +*/ + +#define REGION_USABLE 1 +#define REGION_RESERVED 2 +#define REGION_ACPI_RECL 3 +#define REGION_ACPI_NVS 4 +#define REGION_BAD 5 + +/* +** ACPI 3.0 bit fields +*/ + +#define REGION_IGNORE 0x01 +#define REGION_NONVOL 0x02 + +/* +** 32-bit and 64-bit address values as 64-bit literals +*/ + +#define ADDR_BIT_32 0x0000000100000000LL +#define ADDR_LOW_HALF 0x00000000ffffffffLL +#define ADDR_HIGH_HALR 0xffffffff00000000LL + +#define ADDR_32_MAX ADDR_LOW_HALF +#define ADDR_64_FIRST ADDR_BIT_32 + +/* +** PRIVATE GLOBAL VARIABLES +*/ + +// freespace pools +static block_t *free_pages; +static block_t *free_slices; + +// initialization status +static int km_initialized = 0; + +/* +** IMPORTED GLOBAL VARIABLES +*/ + +extern int _end; // end of the BSS section - provided by the linker + +/* +** FUNCTIONS +*/ + +/* +** FREE LIST MANAGEMENT +*/ + +/** +** Name: add_block +** +** Add a block to the free list. The contents of the block +** will be modified. +** +** @param[in] base Base address of the block +** @param[in] length Block length, in bytes +*/ +static void add_block( uint32_t base, uint32_t length ) { + block_t *block; + + // don't add it if it isn't at least 4K + if( length < SZ_PAGE ) { + return; + } + + // only want to add multiples of 4K; check the lower bits + if( (length & 0xfff) != 0 ) { + // round it down to 4K + length &= 0xfffff000; + } + + // create the "block" + + block = (block_t *) base; + block->pages = B2P(length); + block->next = NULL; + +#if TRACING_KMEM_FREE + cio_printf( "KM: add(%08x,%u): addr %08x len %u\n", + base, length, (uint32_t)block, block->length ); +#endif + + /* + ** We maintain the free list in order by address, to simplify + ** coalescing adjacent free blocks. + ** + ** Handle the easiest case first. + */ + + if( free_pages == NULL ) { + free_pages = block; + return; + } + + /* + ** Unfortunately, it's not always that easy.... + ** + ** Find the correct insertion spot. + */ + + block_t *prev, *curr; + + prev = NULL; + curr = free_pages; + + while( curr && curr < block ) { + prev = curr; + curr = curr->next; + } + + // the new block always points to its successor + block->next = curr; + + /* + ** If prev is NULL, we're adding at the front; otherwise, + ** we're adding after some other entry (middle or end). + */ + + if( prev == NULL ) { + // sanity check - both pointers can't be NULL + assert( curr ); + // add at the beginning + free_pages = block; + } else { + // inserting in the middle or at the end + prev->next = block; + } +} + +/** +** Name: km_init +** +** Find what memory is present on the system and +** construct the list of free memory blocks. +** +** Dependencies: +** Must be called before any other init routine that uses +** dynamic storage is called. +*/ +void km_init( void ) { + int32_t entries; + region_t *region; + uint64_t cutoff; + +#if TRACING_INIT + // announce that we're starting initialization + cio_puts( " Kmem" ); +#endif + + // initially, nothing in the free lists + free_slices = NULL; + free_pages = NULL; + + /* + ** We ignore all memory below the end of our OS. In theory, + ** we should be able to re-use much of that space; in practice, + ** this is safer. + */ + + // set our cutoff point as the end of the BSS section + cutoff = (uint32_t) &_end; + + // round it up to the next multiple of 4K (0x1000) + if( cutoff & 0xfffLL ) { + cutoff &= 0xfffff000LL; + cutoff += 0x1000LL; + } + + // get the list length + entries = *((int32_t *) MMAP_ADDRESS); + +#if TRACING_KEMEM + cio_printf( "\nKmem: %d regions\n", entries ); +#endif + + // if there are no entries, we have nothing to do! + if( entries < 1 ) { // note: entries == -1 could occur! + return; + } + + // iterate through the entries, adding things to the freelist + + region = ((region_t *) (MMAP_ADDRESS + 4)); + + for( int i = 0; i < entries; ++i, ++region ) { + +#if TRACING_KMEM + // report this region + cio_printf( "%3d: ", i ); + cio_printf( " base %08x%08x", + region->base.HIGH, region->base.LOW ); + cio_printf( " len %08x%08x", + region->length.HIGH, region->length.LOW ); + cio_printf( " type %08x acpi %08x", + region->type, region->acpi ); +#endif + + /* + ** Determine whether or not we should ignore this region. + ** + ** We ignore regions for several reasons: + ** + ** ACPI indicates it should be ignored + ** ACPI indicates it's non-volatile memory + ** Region type isn't "usable" + ** Region is above the 4GB address limit + ** + ** Currently, only "normal" (type 1) regions are considered + ** "usable" for our purposes. We could potentially expand + ** this to include ACPI "reclaimable" memory. + */ + + // first, check the ACPI one-bit flags + + if( ((region->acpi) & REGION_IGNORE) == 0 ) { + cio_puts( " IGN\n" ); + continue; + } + + if( ((region->acpi) & REGION_NONVOL) != 0 ) { + cio_puts( " NVOL\n" ); + continue; // we'll ignore this, too + } + + // next, the region type + + if( (region->type) != REGION_USABLE ) { + cio_puts( " RCLM\n" ); + continue; // we won't attempt to reclaim ACPI memory (yet) + } + + // OK, we have a "normal" memory region - verify that it's usable + + // ignore it if it's above 4GB + if( region->base.HIGH != 0 ) { + cio_puts( " 4GB+\n" ); + continue; + } + + // grab the two 64-bit values to simplify things + uint64_t base = region->base.all; + uint64_t length = region->length.all; + + // see if it's below our arbitrary cutoff point + if( base < cutoff ) { + + // is the whole thing too low, or just part? + if( (base + length) < cutoff ) { + // it's all below the cutoff! + cio_puts( " LOW\n" ); + continue; + } + + // recalculate the length, starting at our cutoff point + uint64_t loss = cutoff - base; + + // reset the length and the base address + length -= loss; + base = cutoff; + } + + // see if it extends beyond the 4GB boundary + + if( (base + length) > ADDR_32_MAX ) { + + // OK, it extends beyond the 32-bit limit; figure out + // how far over it goes, and lop off that portion + + uint64_t loss = (base + length) - ADDR_64_FIRST; + length -= loss; + } + + // we survived the gauntlet - add the new block + + cio_puts( " OK\n" ); + + uint32_t b32 = base & ADDR_LOW_HALF; + uint32_t l32 = length & ADDR_LOW_HALF; + + add_block( b32, l32 ); + } + + // record the initialization + km_initialized = 1; +} + +/** +** Name: km_dump +** +** Dump the current contents of the free list to the console +*/ +void km_dump( void ) { + block_t *block; + + cio_printf( "&_free_pages=%08x\n", &_free_pages ); + + for( block = _free_pages; block != NULL; block = block->next ) { + cio_printf( + "block @ 0x%08x 0x%08x pages (ends at 0x%08x) next @ 0x%08x\n", + block, block->pages, P2B(block->pages) + (uint32_t) block, + block->next ); + } + +} + +/* +** PAGE MANAGEMENT +*/ + +/** +** Name: km_page_alloc +** +** Allocate a page of memory from the free list. +** +** @param[in] count Number of contiguous pages desired +** +** @return a pointer to the beginning of the first allocated page, +** or NULL if no memory is available +*/ +void *km_page_alloc( unsigned int count ) { + + assert( km_initialized ); + + // make sure we actually need to do something! + if( count < 1 ) { + return( NULL ); + } + +#if TRACING_KMEM_FREE + cio_printf( "KM: pg_alloc(%u)", count ); +#endif + + /* + ** Look for the first entry that is large enough. + */ + + // pointer to the current block + block_t *block = free_pages; + + // pointer to where the pointer to the current block is + block_t **pointer = &free_pages; + + while( block != NULL && block->pages < count ){ + pointer = &block->next; + block = *pointer; + } + + // did we find a big enough block? + if( block == NULL ){ + // nope! +#if TRACING_KMEM_FREE + cio_puts( " FAIL\n" ); +#endif + return( NULL ); + } + + // found one! check the length + + if( block->pages == count ) { + + // exactly the right size - unlink it from the list + + *pointer = block->next; + + } else { + + // bigger than we need - carve the amount we need off + // the beginning of this block + + // remember where this chunk begins + block_t *chunk = block; + + // how much space will be left over? + int excess = block->pages - count; + + // find the start of the new fragment + block_t *fragment = (block_t *) ( (uint8_t *) block + P2B(count) ); + + // set the length and link for the new fragment + fragment->pages = excess; + fragment->next = block->next; + + // replace this chunk with the fragment + *pointer = fragment; + + // return this chunk + block = chunk; + } + +#if TRACING_KMEM_FREE + cio_printf( " -> %08x\n", (uint32_t) block ); +#endif + + return( block ); +} + +/** +** Name: km_page_free +** +** Returns a memory block to the list of available blocks, +** combining it with adjacent blocks if they're present. +** +** CRITICAL ASSUMPTION: multi-page blocks will be freed one page +** at a time! +** +** @param[in] block Pointer to the page to be returned to the free list +*/ +void km_page_free( void *block ){ + block_t *used; + block_t *prev; + block_t *curr; + + assert( km_initialized ); + + /* + ** Don't do anything if the address is NULL. + */ + if( block == NULL ){ + return; + } + +#if TRACING_KMEM_FREE + cio_printf( "KM: pg_free(%08x)", (uint32_t) block ); +#endif + + used = (block_t *) block; + + /* + ** CRITICAL ASSUMPTION + ** + ** We assume that any multi-page block that is being freed will + ** be freed one page at a time. We make this assumption because we + ** don't track allocation sizes. We can't use the simple "allocate + ** four extra bytes before the returned pointer" scheme to do this + ** because we're managing pages, and the pointers we return must point + ** to page boundaries, so we would wind up allocating an extra page + ** for each allocation. + ** + ** Alternatively, we could keep an array of addresses and block + ** sizes ourselves, but that feels clunky, and would risk running out + ** of table entries if there are lots of allocations (assuming we use + ** a 4KB page to hold the table, at eight bytes per entry we would have + ** 512 entries per page). + ** + ** IF THIS ASSUMPTION CHANGES, THIS CODE MUST BE FIXED!!! + */ + + used->pages = 1; + + /* + ** Advance through the list until current and previous + ** straddle the place where the new block should be inserted. + */ + prev = NULL; + curr = free_pages; + + while( curr != NULL && curr < used ){ + prev = curr; + curr = curr->next; + } + + /* + ** At this point, we have the following list structure: + ** + ** .... BLOCK BLOCK .... + ** (*prev) ^ (*curr) + ** | + ** "used" goes here + ** + ** We may need to merge the inserted block with either its + ** predecessor or its successor (or both). + */ + + /* + ** If this is not the first block in the resulting list, + ** we may need to merge it with its predecessor. + */ + if( prev != NULL ){ + + // There is a predecessor. Check to see if we need to merge. + if( adjacent( prev, used ) ){ + + // yes - merge them + prev->pages += used->pages; + + // the predecessor becomes the "newly inserted" block, + // because we still need to check to see if we should + // merge with the successor + used = prev; + + } else { + + // Not adjacent - just insert the new block + // between the predecessor and the successor. + used->next = prev->next; + prev->next = used; + + } + + } else { + + // Yes, it is first. Update the list pointer to insert it. + used->next = free_pages; + free_pages = used; + + } + + /* + ** If this is not the last block in the resulting list, + ** we may (also) need to merge it with its successor. + */ + if( curr != NULL ){ + + // No. Check to see if it should be merged with the successor. + if( adjacent( used, curr ) ){ + + // Yes, combine them. + used->next = curr->next; + used->pages += curr->pages; + + } + } +} + +/* +** SLICE MANAGEMENT +*/ + +/* +** Slices are 1024-byte fragments from pages. We maintain a free list of +** slices for those parts of the OS which don't need full 4096-byte chunks +** of space (e.g., the QNode and Queue allocators). +*/ + +/** +** Name: carve_slices +** +** Allocate a page and split it into four slices; If no +** memory is available, we panic. +*/ +static void carve_slices( void ) { + void *page; + + // get a page + page = km_page_alloc( 1 ); + + // allocation failure is a show-stopping problem + assert( page ); + + // we have the page; create the four slices from it + uint8_t *ptr = (uint8_t *) page; + for( int i = 0; i < 4; ++i ) { + km_slice_free( (void *) ptr ); + ptr += SZ_SLICE; + } +} + +/** +** Name: km_slice_alloc +** +** Dynamically allocates a slice (1/4 of a page). If no +** memory is available, we panic. +** +** @return a pointer to the allocated slice +*/ +void *km_slice_alloc( void ) { + block_t *slice; + + assert( km_initialized ); + +#if TRACING_KMEM_FREE + cio_printf( "KM: sl_alloc()\n" ); +#endif + + // if we are out of slices, create a few more + if( free_slices == NULL ) { + carve_slices(); + } + + // take the first one from the free list + slice = free_slices; + assert( slice != NULL ); + + // unlink it + free_slices = slice->next; + + // make it nice and shiny for the caller + memclr( (void *) slice, SZ_SLICE ); + + return( slice ); +} + +/** +** Name: km_slice_free +** +** Returns a slice to the list of available slices. +** +** We make no attempt to merge slices, as they are independent +** blocks of memory (unlike pages). +** +** @param[in] block Pointer to the slice (1/4 page) to be freed +*/ +void km_slice_free( void *block ) { + block_t *slice = (block_t *) block; + + assert( km_initialized ); + +#if TRACING_KMEM_FREE + cio_printf( "KM: sl_free(%08x)\n", (uint32_t) block ); +#endif + + // just add it to the front of the free list + slice->pages = SZ_SLICE; + slice->next = free_slices; + free_slices = slice; +} diff --git a/util/alternatives/lib.c b/util/alternatives/lib.c new file mode 100644 index 0000000..4b7a9ed --- /dev/null +++ b/util/alternatives/lib.c @@ -0,0 +1,56 @@ +/** +** @file lib.c +** +** @author Numerous CSCI-452 classes +** +** @brief C implementations of common library functions +** +** These are callable from either kernel or user code. Care should be taken +** that user code is linked against these separately from kernel code, to +** ensure separation of the address spaces. +** +** This file exists to pull them all in as a single object file. +*/ + +#include + +#include + +/* +********************************************** +** MEMORY MANIPULATION FUNCTIONS +********************************************** +*/ + +#include "common/memset.c" +#include "common/memclr.c" +#include "common/memcpy.c" + +/* +********************************************** +** STRING MANIPULATION FUNCTIONS +********************************************** +*/ + +#include "common/str2int.c" +#include "common/strlen.c" +#include "common/strcmp.c" +#include "common/strcpy.c" +#include "common/strcat.c" +#include "common/pad.c" +#include "common/padstr.c" +#include "common/sprint.c" + +/* +********************************************** +** CONVERSION FUNCTIONS +********************************************** +*/ + +#include "common/cvtuns0.c" +#include "common/cvtuns.c" +#include "common/cvtdec0.c" +#include "common/cvtdec.c" +#include "common/cvthex.c" +#include "common/cvtoct.c" +#include "common/bound.c" diff --git a/util/gdbinit.tmpl b/util/gdbinit.tmpl new file mode 100644 index 0000000..d9a981d --- /dev/null +++ b/util/gdbinit.tmpl @@ -0,0 +1,31 @@ +# adapted from the xv6 .gdbinit.tmpl file +set $lastcs = -1 + +define hook-stop + # There doesn't seem to be a good way to detect if we're in 16- or + # 32-bit mode, but we always run with CS == 8 in 32-bit mode. + if $cs == 8 || $cs == 27 + if $lastcs != 8 && $lastcs != 27 + set architecture i386 + end + x/i $pc + else + if $lastcs == -1 || $lastcs == 8 || $lastcs == 27 + set architecture i8086 + end + # Translate the segment:offset into a physical address + printf "[%4x:%4x] ", $cs, $eip + x/i $cs*16+$eip + end + set $lastcs = $cs +end + +echo + target remote localhost:1234\n +target remote localhost:1234 + +# If this fails, it's probably because your GDB doesn't support ELF. +# Look at the tools page at +# http://pdos.csail.mit.edu/6.828/2009/tools.html +# for instructions on building GDB with ELF support. +echo + symbol-file build/kernel/kernel\n +symbol-file build/kernel/kernel diff --git a/util/listblob.c b/util/listblob.c new file mode 100644 index 0000000..07523a6 --- /dev/null +++ b/util/listblob.c @@ -0,0 +1,248 @@ +/** +** @file listblob.c +** +** @author Warren R. Carithers +** +** Examine a binary blob of ELF files. +*/ +#define _DEFAULT_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** Blob file organization +** +** The file begins with a four-byte magic number and a four-byte integer +** indicating the number of ELF files contained in the blob. This is +** followed by an array of 32-byte file entries, and then the contents +** of the ELF files in the order they appear in the program file table. +** +** Bytes Contents +** ----- ---------------------------- +** 0 - 3 File magic number ("BLB\0") +** 4 - 7 Number of ELF files in blob ("n") +** 8 - n*32+8 Program file table +** n*32+9 - ? ELF file contents +** +** Each program file table entry contains the following information: +** +** name File name (up to 19 characters long) +** offset Byte offset to the ELF header for this file +** size Size of this ELF file, in bytes +** flags Flags related to this file +*/ + +// blob header: 8 bytes +typedef struct header_s { + char magic[4]; + uint32_t num; +} header_t; + +// The program table entry is 32 bytes long. To accomplish this, the +// name field is 20 bytes long, which allows file names of 19 characters +// (followed by a trailing NUL byte). +// +// If that field is made longer, it should be incremented in multiples +// of four to avoid the insertion of padding bytes. +#define NAMELEN 20 + +// program descriptor: 32 bytes +typedef struct prog_s { + char name[NAMELEN]; // truncated name (19 chars plus NUL) + uint32_t offset; // offset from the beginning of the blob + uint32_t size; // size of this ELF module + uint32_t flags; // miscellaneous flags +} prog_t; + +// modules must be written as multiples of eight bytes +#define FL_ROUNDUP 0x00000001 + +// mask for mod 8 checking +#define FSIZE_MASK 0x00000007 + +// program list entry +typedef struct node_s { + prog_t *data; + struct node_s *next; +} node_t; + +node_t *progs, *last_prog; // list pointers +uint32_t n_progs; // number of files being copied +uint32_t offset; // current file area offset +bool defs = false; // print CPP #defines? +bool enums = false; // print C enums? + +// header string for the userids.h file +const char header[] = +"/**\n" +"** @file userids.h\n" +"**\n" +"** @author Warren R. Carithers\n" +"**\n" +"** @brief IDs for user-level programs\n" +"**\n" +"** NOTE: this file is automatically generated when the user.img file\n" +"** is created. Do not edit this manually!\n" +"*/\n" +"\n" +"#ifndef USERIDS_H_\n" +"#define USERIDS_H_\n" +"\n" +"#ifndef ASM_SRC\n" +"/*\n" +"** These IDs are used to identify the various user programs.\n" +"** Each call to exec() will provide one of these as the first\n" +"** argument.\n" +"**\n" +"** This list should be updated if/when the collection of\n" +"** user processes changes.\n" +"*/\n" +"enum users_e {" +; + +// trailer string for the userids.h file +const char trailer[] = +"\n\t// sentinel\n\t, N_USERS\n" +"};\n" +"#endif /* !ASM_SRC */\n" +"\n" +"#endif" +; + +/** +** Name: process +** +** Process a program list entry +** +** @param num Program list index +** @param prog Pointer to the program list entry +*/ +void process( uint32_t num, prog_t *prog ) { + + if( defs || enums ) { + + char *slash = strrchr( prog->name, '/' ); + if( slash == NULL ) { + slash = prog->name; + } else { + ++slash; + } + + slash[0] = toupper(slash[0]); + + if( defs ) { + + // just printing #define statements + printf( "#define %-15s %2d\n", prog->name, num ); + + } else { + + // printing a new userids.h file + if( num == 0 ) { + // first one, so print the file header + puts( header ); + putchar( '\t' ); + } else { + // second or later entry; limit to 8 per line + fputs( ((num & 0x7) == 0 ) ? ",\n\t" : ", ", stdout ); + } + printf( "%s", prog->name ); + } + + } else { + + // just printing information + printf( "Entry %2d: ", num ); + printf( "%-s,", prog->name ); + printf( " offset 0x%x, size 0x%x, flags %08x\n", + prog->offset, prog->size, prog->flags ); + } +} + +void usage( char *name ) { + fprintf( stderr, "usage: %s [-d | -e] blob_name\n", name ); +} + +int main( int argc, char *argv[] ) { + + if( argc < 2 || argc > 3) { + usage( argv[0] ); + exit( 1 ); + } + + int nameix = 1; + + // could use getopt() for this, but this is easy enough + if( argc == 3 ) { + if( strcmp(argv[1],"-d") == 0 ) { + defs = true; + } else if( strcmp(argv[1],"-e") == 0 ) { + enums = true; + } else { + usage( argv[0] ); + exit( 1 ); + } + nameix = 2; + } + + char *name = argv[nameix]; + + int fd = open( name, O_RDONLY ); + if( fd < 0 ) { + perror( name ); + exit( 1 ); + } + + header_t hdr; + + int n = read( fd, &hdr, sizeof(header_t) ); + if( n != sizeof(header_t) ) { + fprintf( stderr, "%s: header read returned only %d bytes\n", name, n ); + close( fd ); + exit( 1 ); + } + + if( strcmp(hdr.magic,"BLB") != 0 ) { + fprintf( stderr, "%s: bad magic number\n", name ); + close( fd ); + exit( 1 ); + } + + if( hdr.num < 1 ) { + fprintf( stderr, "%s: no programs in blob?\n", name ); + close( fd ); + exit( 1 ); + } + + prog_t progs[hdr.num]; + + n = read( fd, progs, hdr.num * sizeof(prog_t) ); + if( n != (int) (hdr.num * sizeof(prog_t)) ) { + + fprintf( stderr, "%s: prog table only %d bytes, expected %lu\n", + name, n, hdr.num * sizeof(prog_t) ); + close( fd ); + exit( 1 ); + } + + for( uint32_t i = 0; i < hdr.num; ++i ) { + process( i, &progs[i] ); + } + + if( enums ) { + // print the file trailer + puts( trailer ); + } + + close( fd ); + return 0; + +} diff --git a/util/mergedep.pl b/util/mergedep.pl new file mode 100644 index 0000000..1730d53 --- /dev/null +++ b/util/mergedep.pl @@ -0,0 +1,86 @@ +#!/usr/bin/perl +# Copyright 2003 Bryan Ford +# Distributed under the GNU General Public License. +# +# Usage: mergedep [ ...] +# +# This script merges the contents of all specified +# on the command line into the single file , +# which may or may not previously exist. +# Dependencies in the will override +# any existing dependencies for the same targets in . +# The are deleted after is updated. +# +# The are typically generated by GCC with the -MD option, +# and the is typically included from a Makefile, +# as shown here for GNU 'make': +# +# .deps: $(wildcard *.d) +# perl mergedep $@ $^ +# -include .deps +# +# This script properly handles multiple dependencies per , +# including dependencies having no target, +# so it is compatible with GCC3's -MP option. +# + +sub readdeps { + my $filename = shift; + + open(DEPFILE, $filename) or return 0; + while () { + if (/([^:]*):([^\\:]*)([\\]?)$/) { + my $target = $1; + my $deplines = $2; + my $slash = $3; + while ($slash ne '') { + $_ = ; + defined($_) or die + "Unterminated dependency in $filename"; + /(^[ \t][^\\]*)([\\]?)$/ or die + "Bad continuation line in $filename"; + $deplines = "$deplines\\\n$1"; + $slash = $2; + } + #print "DEPENDENCY [[$target]]: [[$deplines]]\n"; + $dephash{$target} = $deplines; + } elsif (/^[#]?[ \t]*$/) { + # ignore blank lines and comments + } else { + die "Bad dependency line in $filename: $_"; + } + } + close DEPFILE; + return 1; +} + + +if ($#ARGV < 0) { + print "Usage: mergedep [ ..]\n"; + exit(1); +} + +%dephash = (); + +# Read the main dependency file +$maindeps = $ARGV[0]; +readdeps($maindeps); + +# Read and merge in the new dependency files +foreach $i (1 .. $#ARGV) { + readdeps($ARGV[$i]) or die "Can't open $ARGV[$i]"; +} + +# Update the main dependency file +open(DEPFILE, ">$maindeps.tmp") or die "Can't open output file $maindeps.tmp"; +foreach $target (keys %dephash) { + print DEPFILE "$target:$dephash{$target}"; +} +close DEPFILE; +rename("$maindeps.tmp", "$maindeps") or die "Can't overwrite $maindeps"; + +# Finally, delete the new dependency files +foreach $i (1 .. $#ARGV) { + unlink($ARGV[$i]) or print "Error removing $ARGV[$i]\n"; +} + diff --git a/util/mkblob.c b/util/mkblob.c new file mode 100644 index 0000000..32c67dd --- /dev/null +++ b/util/mkblob.c @@ -0,0 +1,324 @@ +/** +** @file mkblob.c +** +** @author Warren R. Carithers +** +** Create a binary blob from a collection of ELF files. +*/ +#define _DEFAULT_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** Blob file organization +** +** The file begins with a four-byte magic number and a four-byte integer +** indicating the number of ELF files contained in the blob. This is +** followed by an array of 32-byte file table entries, and then the contents +** of the ELF files in the order they appear in the program file table. +** +** Bytes Contents +** ----- ---------------------------- +** 0 - 3 File magic number ("BLB\0") +** 4 - 7 Number of ELF files in blob ("n") +** 8 - n*32+8 Program file table +** n*32+9 - ? ELF file contents +** +** Each program file table entry contains the following information: +** +** name File name (up to 19 characters long) +** offset Byte offset to the ELF header for this file +** size Size of this ELF file, in bytes +** flags Flags related to this file +*/ + +// blob header +typedef struct header_s { + char magic[4]; + uint32_t num; +} header_t; + +// length of the file name field +#define NAMELEN 20 + +// program descriptor +typedef struct prog_s { + char name[NAMELEN]; // truncated name (15 chars) + uint32_t offset; // offset from the beginning of the blob + uint32_t size; // size of this ELF module + uint32_t flags; // miscellaneous flags +} prog_t; + +// modules must be written as multiples of eight bytes +#define FL_ROUNDUP 0x00000001 + +// mask for mod 8 checking +#define FSIZE_MASK 0x00000007 + +// program list entry +typedef struct node_s { + prog_t *data; + char *fullname; + struct node_s *next; +} node_t; + +node_t *progs, *last_prog; // list pointers +uint32_t n_progs; // number of files being copied +uint32_t offset; // current file area offset + +/** +** Name: process +** +** Do the initial processing for an ELF file +** +** @param name The name of the file +*/ +void process( const char *name ) { + struct stat info; + + // check the name length + if( strlen(name) >= NAMELEN ) { + fprintf( stderr, "%s: name exceeds length limit (%d)\n", + name, NAMELEN-1 ); + return; + } + + // does it exist? + if( stat(name,&info) < 0 ) { + perror( name ); + return; + } + + // is it a regular file? + if( !S_ISREG(info.st_mode) ) { + fprintf( stderr, "%s: not a regular file\n", name ); + return; + } + + // open it and check the file header + int fd = open( name, O_RDONLY ); + if( fd < 0 ) { + perror( name ); + return; + } + + // read and check the ELF header + Elf32_Ehdr hdr; + int n = read( fd, &hdr, sizeof(Elf32_Ehdr) ); + close( fd ); + + if( n != sizeof(Elf32_Ehdr) ) { + fprintf( stderr, "%s: header read was short - only %d\n", name, n ); + return; + } + + if( hdr.e_ident[EI_MAG0] != ELFMAG0 || + hdr.e_ident[EI_MAG1] != ELFMAG1 || + hdr.e_ident[EI_MAG2] != ELFMAG2 || + hdr.e_ident[EI_MAG3] != ELFMAG3 ) { + fprintf( stderr, "%s: bad ELF magic number\n", name ); + return; + } + + // ok, it's a valid ELF file - create the prog list entry + prog_t *new = calloc( 1, sizeof(prog_t) ); + if( new == NULL ) { + fprintf( stderr, "%s: calloc prog returned NULL\n", name ); + return; + } + + node_t *node = calloc( 1, sizeof(node_t) ); + if( node == NULL ) { + free( new ); + fprintf( stderr, "%s: calloc node returned NULL\n", name ); + return; + } + + node->data = new; + node->fullname = strdup( name ); + + // copy in the name + + // only want the last component + const char *slash = strrchr( name, '/' ); + if( slash == NULL ) { + // only the file name + slash = name; + } else { + // skip the slash + ++slash; + } + + strncpy( new->name, slash, sizeof(new->name)-1 ); + new->offset = offset; + new->size = info.st_size; + + // bump our counters + ++n_progs; + offset += info.st_size; + + // make sure it's a multiple of eight bytes long + if( (info.st_size & FSIZE_MASK) != 0 ) { + // nope, so we must round it up when we write it out + new->flags |= FL_ROUNDUP; + // increases the offset to the next file + offset += 8 - (info.st_size & FSIZE_MASK); + } + + // add to the list + if( progs == NULL ) { + // first entry + progs = node; + } else { + // add to the end + if( last_prog == NULL ) { + fprintf( stderr, "%s: progs ! NULL, last_prog is NULL\n", name ); + free( new ); + free( node->fullname ); + free( node ); + return; + } + last_prog->next = node; + } + last_prog = node; +} + +/** +** Name: copy +** +** Copy the contents of a program list entry into the blob +** +** @param ofd The output FILE* to be written +** @param prog Pointer to the program list entry for the file +*/ +void copy( FILE *ofd, node_t *node ) { + + prog_t *prog = node->data; + + // open it so we can copy it + int fd = open( node->fullname, O_RDONLY ); + if( fd < 0 ) { + perror( node->fullname ); + return; + } + + uint8_t buf[512]; + + // copy it block-by-block + do { + int n = read( fd, buf, 512); + // no bytes --> we're done + if( n < 1 ) { + break; + } + // copy it, and verify the copy count + int k = fwrite( buf, 1, n, ofd ); + if( k != n ) { + fprintf( stderr, "%s: write of %d returned %d\n", + prog->name, n, k ); + } + } while( 1 ); + + printf( "%s: copied %d", prog->name, prog->size ); + + // do we need to round up? + if( (prog->flags & FL_ROUNDUP) != 0 ) { + + // we'll fill with NUL bytes + uint64_t filler = 0; + + // how many filler bytes do we need? + int nbytes = 8 - (prog->size & FSIZE_MASK); + + // do it, and check the transfer count to be sure + int n = fwrite( &filler, 1, nbytes, ofd ); + if( n != nbytes ) { + fprintf( stderr, "%s: fill write of %d returned %d\n", + prog->name, nbytes, n ); + } + + // report that we added some filler bytes + printf( "(+%d)", n ); + } + puts( " bytes" ); + + // all done! + close( fd ); +} + +int main( int argc, char *argv[] ) { + + // construct program list + for( int i = 1; i < argc; ++i ) { + process( argv[i] ); + } + + if( n_progs < 1 ) { + fputs( "Nothing to do... exiting.", stderr ); + exit( 0 ); + } + + // create the output file + FILE *ofd; + ofd = fopen( "user.img", "wb" ); + if( ofd == NULL ) { + perror( "user.img" ); + exit( 1 ); + } + + printf( "Processing %d ELF files\n", n_progs ); + + // we need to adjust the offset values so they are relative to the + // start of the blob, not relative to the start of the file area. + // do this by adding the sum of the file header and program entries + // to each offset field. + + uint32_t hlen = sizeof(header_t) + n_progs * sizeof(prog_t); + node_t *curr = progs; + while( curr != NULL ) { + curr->data->offset += hlen; + curr = curr->next; + } + + // write out the blob header + header_t hdr = { "BLB", n_progs }; + if( fwrite(&hdr,sizeof(header_t),1,ofd) != 1 ) { + perror( "blob header" ); + fclose( ofd ); + exit( 1 ); + } + + // next, the program entries + curr = progs; + while( curr != NULL ) { + if( fwrite(curr->data,sizeof(prog_t),1,ofd) != 1 ) { + perror( "blob prog entry write" ); + fclose( ofd ); + exit( 1 ); + } + curr = curr->next; + } + + // finally, copy the files + curr = progs; + while( curr != NULL ) { + prog_t *prog = curr->data; + copy( ofd, curr ); + node_t *tmp = curr; + curr = curr->next; + free( tmp->data ); + free( tmp->fullname ); + free( tmp ); + } + + fclose( ofd ); + + return 0; +} diff --git a/vmtables.d b/vmtables.d new file mode 100644 index 0000000..6fbb02c --- /dev/null +++ b/vmtables.d @@ -0,0 +1,5 @@ +vmtables.o: kernel/vmtables.c include/common.h include/types.h \ + include/params.h include/defs.h include/kdefs.h include/debug.h \ + include/cio.h include/support.h include/lib.h include/klib.h \ + include/x86/ops.h include/kmem.h include/procs.h include/vm.h \ + include/x86/arch.h -- cgit v1.2.3-freya