summaryrefslogtreecommitdiff
path: root/module/language/sassy/flat-bin.scm
diff options
context:
space:
mode:
Diffstat (limited to 'module/language/sassy/flat-bin.scm')
-rw-r--r--module/language/sassy/flat-bin.scm163
1 files changed, 163 insertions, 0 deletions
diff --git a/module/language/sassy/flat-bin.scm b/module/language/sassy/flat-bin.scm
new file mode 100644
index 000000000..410f4573b
--- /dev/null
+++ b/module/language/sassy/flat-bin.scm
@@ -0,0 +1,163 @@
+; flat-bin.scm - create bin files from Sassy's output
+; Copyright (C) 2005 Jonathan Kraut
+
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2.1 of the License, or (at your option) any later version.
+
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+; Contact:
+; Jonathan Kraut
+; 4130 43 ST #C2
+; Sunnyside, NY 11104
+; jak76@columbia.edu
+
+; see file COPYING in the top of Sassy's distribution directory
+
+
+; module flat-bin
+; import api
+; export all
+
+
+
+; This is a good demonstration of how to use the output API, and we
+; should probably include it in chapter 7 of the docs.
+
+; usage:
+
+; procedure:
+; (sassy-make-bin output-file sassy-output opts ...) => unspecified
+
+; Combines the text and data sections of sassy-output and writes a
+; flat binary file to output-file. If the file already exists it is
+; deleted. Any (org) directive is taken into account, and relocations
+; are performed on absolute references in the data section. The data
+; segment is placed (and aligned properly) immediately after the text
+; segment.
+
+; opts can be none, one or both of the following quoted symbols:
+
+; 'boot : Make the file be an x86 boot-sector. That is, zero-fill the
+; remainder of the file to 510 bytes, and add the x86 boot-sector
+; signature #x55aa to bytes 511 and 512.
+
+; 'stats : Display some stats about the output.
+
+
+
+(define (sassy-make-bin output-file sassy-output . opts)
+
+ (define boot-sector? (memq 'boot opts))
+ (define stats? (memq 'stats opts))
+
+ (define data? (not (zero? (sassy-data-size sassy-output))))
+
+ ; Grap some info for printout stats later.
+
+ (define text-size (sassy-text-size sassy-output))
+ (define data-size (sassy-data-size sassy-output))
+ (define text-pad 0)
+
+ (define (display-stat . itms)
+ (for-each display itms)
+ (newline))
+
+ (define (needed-reloc? x)
+ (and (eq? 'abs (sassy-reloc-type x))
+ (let ((name (sassy-reloc-name x)))
+ (if name
+ (let ((symbol (sassy-symbol-exists? sassy-output name)))
+ (and (eq? 'data (sassy-symbol-section symbol))
+ (not (eq? 'import (sassy-symbol-scope symbol)))))
+ (eq? 'data (sassy-reloc-section x))))))
+
+ ; Align the end of the text-section to the align of the data section.
+ ; The data section will begin at this point in the file.
+ ; (nop) is used as the filler.
+
+ (when data?
+ (push-stack-align (sassy-text-stack sassy-output)
+ (sassy-data-align sassy-output)
+ #x90))
+
+ (set! text-pad (- (sassy-text-size sassy-output) text-size))
+
+ ; Since the text-section is going to be loaded at whatever the given
+ ; (org) was, all absolute relocations in the text section that refer
+ ; to other locations in the text section already have the offset of
+ ; (org) added to them, so we don't have to apply relocations to
+ ; those. And we don't need to relocate relative addresses in the
+ ; text section (and relative relocations aren't allowed in the data
+ ; section).
+
+ ; So, we only need to relocate references to symbols defined in the data
+ ; section, or anonymous relocs in the data section
+
+ ; Also, we need to grab all those references both from the
+ ; text-section _and_ the _data_ section
+
+ (when data?
+ (let ((data-relocs-to-do
+ (filter needed-reloc? (sassy-reloc-list sassy-output))))
+
+ ; Now we get ready to apply the relocations taking into account the new
+ ; end of the text-section (or beginning of the data-section).
+
+ ; For each reloc-to-do, we're going to apply it's patcher
+ ; to the the data-offset plus the value already there
+
+ (let* ((text-offset (sassy-text-org sassy-output))
+ (data-offset (+ text-offset (sassy-text-size sassy-output))))
+ (for-each (lambda (reloc)
+ ((sassy-reloc-patcher reloc)
+ (+ data-offset (sassy-reloc-value reloc))))
+ data-relocs-to-do))
+
+ ; Now all we have to to is append the data to the text, mark it as
+ ; a boot sectior, and spit it out.
+
+ ; The fastest way to tack a data section on to a text section is
+ ; the following
+ ; !!!!NOTE: This actually alters the text section (append!)
+ (push-stack-append! (sassy-text-stack sassy-output)
+ (sassy-data-stack sassy-output))))
+
+ (when boot-sector?
+ ; sanity check
+ (if (> (sassy-text-size sassy-output) 510)
+ (error "segment too big for a boot sector")
+ (begin
+ ; mark it as a boot sector
+ (push-stack-align (sassy-text-stack sassy-output) 510 0)
+ (push-stack-push (sassy-text-stack sassy-output)
+ (list #x55 #xaa)))))
+
+ ; dump to file
+ (when (file-exists? output-file)
+ (delete-file output-file))
+ (with-output-to-file output-file
+ (lambda ()
+ (for-each write-byte (sassy-text-list sassy-output))))
+
+ (when stats?
+ (display-stat "Text size: " text-size " bytes")
+ (display-stat "Data size: " data-size " bytes")
+ (display-stat "Data align: "
+ (sassy-data-align sassy-output)
+ " byte boundary")
+ (display-stat
+ "Total size: "
+ (+ text-size data-size text-pad)
+ " bytes, with " text-pad " bytes of padding in the text section.")
+ (when boot-sector?
+ (display-stat "Made a boot sector"))))