Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
7597 akron1 1
(*
2
    BSD 2-Clause License
3
 
4
    Copyright (c) 2018, 2019, Anton Krotov
5
    All rights reserved.
6
*)
7
 
8
MODULE BIN;
9
 
10
IMPORT LISTS, MACHINE, CHL := CHUNKLISTS, ARITH, UTILS;
11
 
12
 
13
CONST
14
 
15
    RCODE*    = 1;
16
    RDATA*    = 2;
17
    RBSS*     = 3;
18
    RIMP*     = 4;
19
 
20
    PICCODE*  = 5;
21
    PICDATA*  = 6;
22
    PICBSS*   = 7;
23
    PICIMP*   = 8;
24
 
25
    IMPTAB*   = 9;
26
 
27
 
28
TYPE
29
 
30
    RELOC* = POINTER TO RECORD (LISTS.ITEM)
31
 
32
        opcode*: INTEGER;
33
        offset*: INTEGER
34
 
35
    END;
36
 
37
    IMPRT* = POINTER TO RECORD (LISTS.ITEM)
38
 
39
        nameoffs*: INTEGER;
40
        label*:    INTEGER;
41
 
42
        OriginalFirstThunk*,
43
        FirstThunk*: INTEGER
44
 
45
    END;
46
 
47
    EXPRT* = POINTER TO RECORD (LISTS.ITEM)
48
 
49
        nameoffs*: INTEGER;
50
        label*:    INTEGER
51
 
52
    END;
53
 
54
    PROGRAM* = POINTER TO RECORD
55
 
56
        code*:      CHL.BYTELIST;
57
        data*:      CHL.BYTELIST;
58
        labels:     CHL.INTLIST;
59
        bss*:       INTEGER;
60
        stack*:     INTEGER;
61
        vmajor*,
62
        vminor*:    WCHAR;
63
        modname*:   INTEGER;
64
        import*:    CHL.BYTELIST;
65
        export*:    CHL.BYTELIST;
66
        rel_list*:  LISTS.LIST;
67
        imp_list*:  LISTS.LIST;
68
        exp_list*:  LISTS.LIST
69
 
70
    END;
71
 
72
 
73
PROCEDURE create* (NumberOfLabels: INTEGER): PROGRAM;
74
VAR
75
    program:  PROGRAM;
76
    i:        INTEGER;
77
 
78
BEGIN
79
    NEW(program);
80
 
81
    program.bss := 0;
82
 
83
    program.labels := CHL.CreateIntList();
84
    FOR i := 0 TO NumberOfLabels - 1 DO
85
        CHL.PushInt(program.labels, 0)
86
    END;
87
 
88
    program.rel_list := LISTS.create(NIL);
89
    program.imp_list := LISTS.create(NIL);
90
    program.exp_list := LISTS.create(NIL);
91
 
92
    program.data   := CHL.CreateByteList();
93
    program.code   := CHL.CreateByteList();
94
    program.import := CHL.CreateByteList();
95
    program.export := CHL.CreateByteList()
96
 
97
    RETURN program
98
END create;
99
 
100
 
101
PROCEDURE SetParams* (program: PROGRAM; bss, stack: INTEGER; vmajor, vminor: WCHAR);
102
BEGIN
103
    program.bss    := bss;
104
    program.stack  := stack;
105
    program.vmajor := vmajor;
106
    program.vminor := vminor
107
END SetParams;
108
 
109
 
110
PROCEDURE PutReloc* (program: PROGRAM; opcode: INTEGER);
111
VAR
112
    cmd: RELOC;
113
 
114
BEGIN
115
    NEW(cmd);
116
    cmd.opcode := opcode;
117
    cmd.offset := CHL.Length(program.code);
118
    LISTS.push(program.rel_list, cmd)
119
END PutReloc;
120
 
121
 
122
PROCEDURE PutData* (program: PROGRAM; b: BYTE);
123
BEGIN
124
    CHL.PushByte(program.data, b)
125
END PutData;
126
 
127
 
128
PROCEDURE get32le* (array: CHL.BYTELIST; idx: INTEGER): INTEGER;
129
VAR
130
    i: INTEGER;
131
    x: INTEGER;
132
 
133
BEGIN
134
    x := 0;
135
 
136
    FOR i := 3 TO 0 BY -1 DO
137
        x := LSL(x, 8) + CHL.GetByte(array, idx + i)
138
    END;
139
 
140
    IF UTILS.bit_depth = 64 THEN
141
        x := MACHINE.Int32To64(x)
142
    END
143
 
144
    RETURN x
145
END get32le;
146
 
147
 
148
PROCEDURE put32le* (array: CHL.BYTELIST; idx: INTEGER; x: INTEGER);
149
VAR
150
    i: INTEGER;
151
 
152
BEGIN
153
    FOR i := 0 TO 3 DO
154
        CHL.SetByte(array, idx + i, MACHINE.Byte(x, i))
155
    END
156
END put32le;
157
 
158
 
159
PROCEDURE PutData32LE* (program: PROGRAM; x: INTEGER);
160
VAR
161
    i: INTEGER;
162
 
163
BEGIN
164
    FOR i := 0 TO 3 DO
165
        CHL.PushByte(program.data, MACHINE.Byte(x, i))
166
    END
167
END PutData32LE;
168
 
169
 
170
PROCEDURE PutData64LE* (program: PROGRAM; x: INTEGER);
171
VAR
172
    i: INTEGER;
173
 
174
BEGIN
175
    FOR i := 0 TO 7 DO
176
        CHL.PushByte(program.data, MACHINE.Byte(x, i))
177
    END
178
END PutData64LE;
179
 
180
 
181
PROCEDURE PutDataStr* (program: PROGRAM; s: ARRAY OF CHAR);
182
VAR
183
    i: INTEGER;
184
 
185
BEGIN
186
    i := 0;
187
    WHILE s[i] # 0X DO
188
        PutData(program, ORD(s[i]));
189
        INC(i)
190
    END
191
END PutDataStr;
192
 
193
 
194
PROCEDURE PutCode* (program: PROGRAM; b: BYTE);
195
BEGIN
196
    CHL.PushByte(program.code, b)
197
END PutCode;
198
 
199
 
200
PROCEDURE PutCode32LE* (program: PROGRAM; x: INTEGER);
201
VAR
202
    i: INTEGER;
203
 
204
BEGIN
205
    FOR i := 0 TO 3 DO
206
        CHL.PushByte(program.code, MACHINE.Byte(x, i))
207
    END
208
END PutCode32LE;
209
 
210
 
211
PROCEDURE SetLabel* (program: PROGRAM; label, offset: INTEGER);
212
BEGIN
213
    CHL.SetInt(program.labels, label, offset)
214
END SetLabel;
215
 
216
 
217
PROCEDURE Import* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER);
218
VAR
219
    imp: IMPRT;
220
    i:   INTEGER;
221
 
222
BEGIN
223
    CHL.PushByte(program.import, 0);
224
    CHL.PushByte(program.import, 0);
225
 
226
    IF ODD(CHL.Length(program.import)) THEN
227
        CHL.PushByte(program.import, 0)
228
    END;
229
 
230
    NEW(imp);
231
    imp.nameoffs := CHL.Length(program.import);
232
    imp.label := label;
233
    LISTS.push(program.imp_list, imp);
234
 
235
    i := 0;
236
    WHILE name[i] # 0X DO
237
        CHL.PushByte(program.import, ORD(name[i]));
238
        INC(i)
239
    END;
240
    CHL.PushByte(program.import, 0)
241
END Import;
242
 
243
 
244
PROCEDURE less (bytes: CHL.BYTELIST; a, b: EXPRT): BOOLEAN;
245
VAR
246
    i, j: INTEGER;
247
 
248
BEGIN
249
    i := a.nameoffs;
250
    j := b.nameoffs;
251
 
252
    WHILE (CHL.GetByte(bytes, i) # 0) & (CHL.GetByte(bytes, j) # 0) &
253
          (CHL.GetByte(bytes, i) = CHL.GetByte(bytes, j)) DO
254
        INC(i);
255
        INC(j)
256
    END
257
 
258
    RETURN CHL.GetByte(bytes, i) < CHL.GetByte(bytes, j)
259
END less;
260
 
261
 
262
PROCEDURE Export* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER);
263
VAR
264
    exp, cur: EXPRT;
265
    i: INTEGER;
266
 
267
BEGIN
268
    NEW(exp);
269
    exp.nameoffs := CHL.Length(program.export);
270
    exp.label := CHL.GetInt(program.labels, label);
271
 
272
    i := 0;
273
    WHILE name[i] # 0X DO
274
        CHL.PushByte(program.export, ORD(name[i]));
275
        INC(i)
276
    END;
277
    CHL.PushByte(program.export, 0);
278
 
279
    cur := program.exp_list.first(EXPRT);
280
    WHILE (cur # NIL) & less(program.export, cur, exp) DO
281
        cur := cur.next(EXPRT)
282
    END;
283
 
284
    IF cur # NIL THEN
285
        IF cur.prev # NIL THEN
286
            LISTS.insert(program.exp_list, cur.prev, exp)
287
        ELSE
288
            LISTS.insertL(program.exp_list, cur, exp)
289
        END
290
    ELSE
291
        LISTS.push(program.exp_list, exp)
292
    END
293
 
294
END Export;
295
 
296
 
297
PROCEDURE GetIProc* (program: PROGRAM; n: INTEGER): IMPRT;
298
VAR
299
    import: IMPRT;
300
    res:    IMPRT;
301
 
302
BEGIN
303
    import  := program.imp_list.first(IMPRT);
304
 
305
    res := NIL;
306
    WHILE (import # NIL) & (n >= 0) DO
307
        IF import.label # 0 THEN
308
            res := import;
309
            DEC(n)
310
        END;
311
        import := import.next(IMPRT)
312
    END;
313
 
314
    ASSERT(n = -1)
315
    RETURN res
316
END GetIProc;
317
 
318
 
319
PROCEDURE GetLabel* (program: PROGRAM; label: INTEGER): INTEGER;
320
    RETURN CHL.GetInt(program.labels, label)
321
END GetLabel;
322
 
323
 
324
PROCEDURE NewLabel* (program: PROGRAM);
325
BEGIN
326
    CHL.PushInt(program.labels, 0)
327
END NewLabel;
328
 
329
 
330
PROCEDURE fixup* (program: PROGRAM);
331
VAR
332
    rel:    RELOC;
333
    imp:    IMPRT;
334
    nproc:  INTEGER;
335
    L:      INTEGER;
336
 
337
BEGIN
338
 
339
    nproc := 0;
340
    imp := program.imp_list.first(IMPRT);
341
    WHILE imp # NIL DO
342
        IF imp.label # 0 THEN
343
            CHL.SetInt(program.labels, imp.label, nproc);
344
            INC(nproc)
345
        END;
346
        imp := imp.next(IMPRT)
347
    END;
348
 
349
    rel := program.rel_list.first(RELOC);
350
    WHILE rel # NIL DO
351
 
352
        IF rel.opcode IN {RIMP, PICIMP} THEN
353
            L := get32le(program.code, rel.offset);
354
            put32le(program.code, rel.offset, GetLabel(program, L))
355
        END;
356
 
357
        rel := rel.next(RELOC)
358
    END
359
 
360
END fixup;
361
 
362
 
363
PROCEDURE InitArray* (VAR array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR);
364
VAR
365
    i, k: INTEGER;
366
 
367
 
368
    PROCEDURE hexdgt (dgt: CHAR): INTEGER;
369
    VAR
370
        res: INTEGER;
371
 
372
    BEGIN
373
        IF dgt < "A" THEN
374
            res := ORD(dgt) - ORD("0")
375
        ELSE
376
            res := ORD(dgt) - ORD("A") + 10
377
        END
378
 
379
        RETURN res
380
    END hexdgt;
381
 
382
 
383
BEGIN
384
    k := LENGTH(hex);
385
    ASSERT(~ODD(k));
386
    k := k DIV 2;
387
 
388
    FOR i := 0 TO k - 1 DO
389
        array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1])
390
    END;
391
 
392
    idx := idx + k
393
END InitArray;
394
 
395
 
396
END BIN.