Subversion Repositories Kolibri OS

Rev

Rev 7597 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7597 akron1 1
(*
2
    BSD 2-Clause License
3
 
7693 akron1 4
    Copyright (c) 2018, 2019, Anton Krotov
7597 akron1 5
    All rights reserved.
6
*)
7
 
8
MODULE KOS;
9
 
10
IMPORT BIN, WR := WRITER, LISTS, CHL := CHUNKLISTS;
11
 
12
 
13
CONST
14
 
15
    HEADER_SIZE = 36;
16
 
17
    SIZE_OF_DWORD = 4;
18
 
19
 
20
TYPE
21
 
22
    FILE = WR.FILE;
23
 
24
    HEADER = RECORD
25
 
26
        menuet01: ARRAY 9 OF CHAR;
27
        ver, start, size, mem, sp, param, path: INTEGER
28
 
29
    END;
30
 
31
 
32
PROCEDURE align (n, _align: INTEGER): INTEGER;
33
BEGIN
34
    IF n MOD _align # 0 THEN
35
        n := n + _align - (n MOD _align)
36
    END
37
 
38
    RETURN n
39
END align;
40
 
41
 
42
PROCEDURE Import* (program: BIN.PROGRAM; idata: INTEGER; VAR ImportTable: CHL.INTLIST; VAR len, libcount, size: INTEGER);
43
VAR
44
    i:      INTEGER;
45
    import: BIN.IMPRT;
46
 
47
BEGIN
48
    libcount  := 0;
49
    import := program.imp_list.first(BIN.IMPRT);
50
    WHILE import # NIL DO
51
        IF import.label = 0 THEN
52
            INC(libcount)
53
        END;
54
        import := import.next(BIN.IMPRT)
55
    END;
56
 
57
    len  := libcount * 2 + 2;
58
    size := (LISTS.count(program.imp_list) + len + 1) * SIZE_OF_DWORD;
59
 
60
    ImportTable := CHL.CreateIntList();
61
    FOR i := 0 TO size DIV SIZE_OF_DWORD - 1 DO
62
        CHL.PushInt(ImportTable, 0)
63
    END;
64
 
65
    i := 0;
66
    import := program.imp_list.first(BIN.IMPRT);
67
    WHILE import # NIL DO
68
 
69
        IF import.label = 0 THEN
70
            CHL.SetInt(ImportTable, len, 0);
71
            INC(len);
72
            CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD);
73
            INC(i);
74
            CHL.SetInt(ImportTable, i, import.nameoffs + size + idata);
75
            INC(i)
76
        ELSE
77
            CHL.SetInt(ImportTable, len, import.nameoffs + size + idata);
78
            import.label := len * SIZE_OF_DWORD;
79
            INC(len)
80
        END;
81
 
82
        import := import.next(BIN.IMPRT)
83
    END;
84
    CHL.SetInt(ImportTable, len, 0);
85
    CHL.SetInt(ImportTable, i, 0);
86
    CHL.SetInt(ImportTable, i + 1, 0);
87
    INC(len);
88
    size := size + CHL.Length(program.import)
89
END Import;
90
 
91
 
92
PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR);
93
 
94
CONST
95
 
96
    PARAM_SIZE    = 2048;
97
    FileAlignment = 16;
98
 
99
 
100
VAR
101
    header: HEADER;
102
 
103
    base, text, data, idata, bss: INTEGER;
104
 
105
    reloc:   BIN.RELOC;
106
    iproc:   BIN.IMPRT;
107
    L:       INTEGER;
108
    delta:   INTEGER;
109
 
110
    i: INTEGER;
111
 
112
    File: FILE;
113
 
114
    ImportTable: CHL.INTLIST;
115
    ILen, libcount, isize: INTEGER;
116
 
117
    icount, dcount, ccount: INTEGER;
118
 
119
 
120
BEGIN
121
    base := 0;
122
 
123
    icount := CHL.Length(program.import);
124
    dcount := CHL.Length(program.data);
125
    ccount := CHL.Length(program.code);
126
 
127
    text  := base + HEADER_SIZE;
128
    data  := align(text + ccount, FileAlignment);
129
    idata := align(data + dcount, FileAlignment);
130
 
131
    Import(program, idata, ImportTable, ILen, libcount, isize);
132
 
133
    bss := align(idata + isize, FileAlignment);
134
 
135
    header.menuet01 := "MENUET01";
136
    header.ver      :=  1;
137
    header.start    :=  text;
138
    header.size     :=  idata + isize - base;
139
    header.mem      :=  align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment);
140
    header.sp       :=  base + header.mem - PARAM_SIZE * 2;
141
    header.param    :=  header.sp;
142
    header.path     :=  header.param + PARAM_SIZE;
143
 
144
 
145
    reloc := program.rel_list.first(BIN.RELOC);
146
    WHILE reloc # NIL DO
147
 
148
        L := BIN.get32le(program.code, reloc.offset);
149
        delta := 3 - reloc.offset - text;
150
 
151
        CASE reloc.opcode OF
152
 
153
        |BIN.RIMP:
154
              iproc := BIN.GetIProc(program, L);
155
              BIN.put32le(program.code, reloc.offset, idata + iproc.label)
156
 
157
        |BIN.RBSS:
158
              BIN.put32le(program.code, reloc.offset, L + bss)
159
 
160
        |BIN.RDATA:
161
              BIN.put32le(program.code, reloc.offset, L + data)
162
 
163
        |BIN.RCODE:
164
              BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text)
165
 
166
        |BIN.PICDATA:
167
              BIN.put32le(program.code, reloc.offset, L + data + delta)
168
 
169
        |BIN.PICCODE:
170
              BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text + delta)
171
 
172
        |BIN.PICBSS:
173
              BIN.put32le(program.code, reloc.offset, L + bss + delta)
174
 
175
        |BIN.PICIMP:
176
              iproc := BIN.GetIProc(program, L);
177
              BIN.put32le(program.code, reloc.offset, idata + iproc.label + delta)
178
 
179
        |BIN.IMPTAB:
180
              BIN.put32le(program.code, reloc.offset, idata + delta)
181
 
182
        END;
183
 
184
        reloc := reloc.next(BIN.RELOC)
185
    END;
186
 
187
    File := WR.Create(FileName);
188
 
189
    FOR i := 0 TO 7 DO
190
        WR.WriteByte(File, ORD(header.menuet01[i]))
191
    END;
192
 
193
    WR.Write32LE(File, header.ver);
194
    WR.Write32LE(File, header.start);
195
    WR.Write32LE(File, header.size);
196
    WR.Write32LE(File, header.mem);
197
    WR.Write32LE(File, header.sp);
198
    WR.Write32LE(File, header.param);
199
    WR.Write32LE(File, header.path);
7693 akron1 200
 
7597 akron1 201
    CHL.WriteToFile(File, program.code);
202
    WR.Padding(File, FileAlignment);
203
 
204
    CHL.WriteToFile(File, program.data);
205
    WR.Padding(File, FileAlignment);
206
 
207
    FOR i := 0 TO ILen - 1 DO
208
        WR.Write32LE(File, CHL.GetInt(ImportTable, i))
7693 akron1 209
    END;
210
 
7597 akron1 211
    CHL.WriteToFile(File, program.import);
212
 
213
    WR.Close(File)
214
 
215
END write;
216
 
217
 
218
END KOS.