File: embed-boot.rkt

package info (click to toggle)
racket 8.18%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 168,924 kB
  • sloc: ansic: 305,985; lisp: 212,340; pascal: 80,096; sh: 20,464; asm: 15,251; makefile: 1,750; cpp: 1,715; javascript: 1,340; exp: 789; python: 452; csh: 369; perl: 171; xml: 106
file content (159 lines) | stat: -rw-r--r-- 5,804 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#lang racket/base
(require racket/cmdline
         racket/file
         compiler/private/mach-o
         compiler/private/pe-rsrc
         compiler/private/elf
         "adjust-compress.rkt")

(define alt-dests '())
(define rewrites '())
(define target #f)

(command-line
 #:once-each
 [("--compress") "Leave compiled code files as compressed"
  (enable-compress!)]
 [("--target") machine "Select target machine"
  (set! target machine)]
 #:multi
 [("++exe") src dest "Select an alternative executable"
  (set! alt-dests (cons (cons src dest) alt-dests))]
 [("++rewrite") from to "Add an arbitrary string replacement"
  (set! rewrites (cons (cons from to) rewrites))]
 #:args (src-file dest-file petite.boot scheme.boot racket.boot)

 ;; If `src-file` is "", then `dest-file` is used as the src, too

 (define bstr1 (adjust-compress (file->bytes petite.boot)))
 (define bstr2 (adjust-compress (file->bytes scheme.boot)))
 (define bstr3 (adjust-compress (file->bytes racket.boot)))

 (define use-src-file
   (if (equal? src-file "")
       (let ([src-file (path-add-suffix dest-file #"_tmp")])
         (rename-file-or-directory dest-file src-file #t)
         src-file)
       src-file))
 (define (clean-src)
   (unless (eq? use-src-file src-file)
     (delete-file use-src-file)))

 (with-handlers ([exn? (lambda (x)
                         (clean-src)
                         (when (file-exists? dest-file)
                           (delete-file dest-file))
                         (raise x))])
   (define terminator
     ;; A 127 byte teriminates a fasl-read sequence
     #"\177")
   (define data
     (bytes-append bstr1 terminator
                   bstr2 terminator
                   bstr3 terminator))
   (define pos
     (case (or target (path->string (system-library-subpath #f)))
       [("ta6osx" "ti3osx" "tarm64osx" "tppc32osx"
         "x86_64-darwin" "i386-darwin" "aarch64-darwin" "ppc-darwin"
         "x86_64-macosx" "i386-macosx" "aarch64-macosx" "ppc-macsosx")
        ;; Mach-O
        (when (file-exists? dest-file)
          ;; explicit delete to avoid signature unhappiness
          (delete-file dest-file))
        (copy-file use-src-file dest-file)
        (remove-signature dest-file)
        (add-plt-segment dest-file data #:name #"__RKTBOOT")
        ;; Find segment at run time:
        0]
       [("ta6nt" "ti3nt" "tarm64nt"
         "win32\\x86_64" "win32\\i386" "win32\\arm64")
        (copy-file use-src-file dest-file #t)
        (define-values (pe rsrcs) (call-with-input-file*
                                   dest-file
                                   read-pe+resources))
        (define new-rsrcs (resource-set rsrcs
                                        ;; Racket's "user-defined" type for boot:
                                        259
                                        1
                                        1033 ; U.S. English
                                        data))
	(update-resources dest-file pe new-rsrcs)
	;; Find resource at run time:
	0]
       [else
        ;; ELF?
        (define-values (start-pos end-pos any1 any2)
          (add-racket-section use-src-file dest-file #".rackboot"
                              (lambda (pos)
                                (values data 'any1 'any2))))
        (cond
          [start-pos
           ;; Success as ELF
           (file-or-directory-permissions dest-file (file-or-directory-permissions use-src-file 'bits))
           ;; Find ".rackboot" at run time:
           0]
          [else
           ;; Not ELF; just append to the end
           (copy-file use-src-file dest-file #t)
           (define pos (file-size dest-file))
           (call-with-output-file*
            dest-file
            #:exists 'update
            (lambda (o)
              (file-position o pos)
              (write-bytes data o)))
           pos])]))

   (for ([rewrite (in-list rewrites)])
     (define from (car rewrite))
     (define to (cdr rewrite))
     (let loop ()
       (define i (open-input-file dest-file))
       (define m (regexp-match-positions from i))
       (close-input-port i)
       (when m
         (define o (open-output-file dest-file #:exists 'update))
         (file-position o (caar m))
         (display to o)
         (close-output-port o)
         (loop))))

   (define (write-offsets dest-file)
     (define-values (i o) (open-input-output-file dest-file #:exists 'update))
     (define m (regexp-match-positions #rx"BooT FilE OffsetS:" i))
     (unless m
       (error 'embed-boot "cannot find boot-file offset tag"))

     (define terminator-len (bytes-length terminator))

     (define big-endian?
       (if target
           (case target
             [("tppc32osx" "ppc32osx"
                          "tppc32le" "ppc32le"
                          "tppc32fb" "ppc32fb"
                          "tppc32ob" "ppc32ob"
                          "tppc32nb" "ppc32nb"
                          "tpb64b" "pb64b"
                          "tpb32b" "pb32b") #t]
             [else #f])
           (system-big-endian?)))

     (file-position o (cdar m))
     (void (write-bytes (integer->integer-bytes pos 4 #t big-endian?) o))
     (let ([pos (+ pos (bytes-length bstr1) terminator-len)])
       (void (write-bytes (integer->integer-bytes pos 4 #t big-endian?) o))
       (let ([pos (+ pos (bytes-length bstr2) terminator-len)])
         (void (write-bytes (integer->integer-bytes pos 4 #t big-endian?) o))
         (let ([pos (+ pos (bytes-length bstr3) terminator-len)])
           (void (write-bytes (integer->integer-bytes pos 4 #t big-endian?) o))))))

   (cond
    [(null? alt-dests)
     (write-offsets dest-file)]
    [else
     (for ([alt (in-list alt-dests)])
       (copy-file (car alt) (cdr alt) #t)
       (write-offsets (cdr alt)))])

   (clean-src)))