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 MSCOFF;
9
 
10
IMPORT BIN, PE32, KOS, WR := WRITER, UTILS, ERRORS, LISTS, CHL := CHUNKLISTS;
11
 
12
 
13
CONST
14
 
15
    SIZE_OF_DWORD = 4;
16
 
17
    (* SectionHeader.Characteristics *)
18
 
19
    SHC_flat  = 040500020H;
20
    SHC_data  = 0C0500040H;
21
    SHC_bss   = 0C03000C0H;
22
 
23
 
24
TYPE
25
 
26
    FH = PE32.IMAGE_FILE_HEADER;
27
 
28
    SH = PE32.IMAGE_SECTION_HEADER;
29
 
30
 
31
PROCEDURE WriteReloc (File: WR.FILE; VirtualAddress, SymbolTableIndex, Type: INTEGER);
32
BEGIN
33
    WR.Write32LE(File, VirtualAddress);
34
    WR.Write32LE(File, SymbolTableIndex);
35
    WR.Write16LE(File, Type)
36
END WriteReloc;
37
 
38
 
39
PROCEDURE Reloc (program: BIN.PROGRAM; File: WR.FILE);
40
VAR
41
    reloc: BIN.RELOC;
42
 
43
BEGIN
44
    reloc := program.rel_list.first(BIN.RELOC);
45
    WHILE reloc # NIL DO
46
 
47
        CASE reloc.opcode OF
48
 
49
        |BIN.RIMP, BIN.IMPTAB:
50
              WriteReloc(File, reloc.offset, 4, 6)
51
 
52
        |BIN.RBSS:
53
              WriteReloc(File, reloc.offset, 5, 6)
54
 
55
        |BIN.RDATA:
56
              WriteReloc(File, reloc.offset, 2, 6)
57
 
58
        |BIN.RCODE:
59
              WriteReloc(File, reloc.offset, 1, 6)
60
 
61
        END;
62
 
63
        reloc := reloc.next(BIN.RELOC)
64
    END;
65
END Reloc;
66
 
67
 
68
PROCEDURE RelocCount (program: BIN.PROGRAM): INTEGER;
69
VAR
70
    reloc:   BIN.RELOC;
71
    iproc:   BIN.IMPRT;
72
    res, L:  INTEGER;
73
 
74
BEGIN
75
    res := 0;
76
    reloc := program.rel_list.first(BIN.RELOC);
77
    WHILE reloc # NIL DO
78
 
79
        INC(res);
80
 
81
        IF reloc.opcode = BIN.RIMP THEN
82
            L := BIN.get32le(program.code, reloc.offset);
83
            iproc := BIN.GetIProc(program, L);
84
            BIN.put32le(program.code, reloc.offset, iproc.label)
85
        END;
86
 
87
        IF reloc.opcode = BIN.RCODE THEN
88
            L := BIN.get32le(program.code, reloc.offset);
89
            BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L))
90
        END;
91
 
92
        reloc := reloc.next(BIN.RELOC)
93
    END
94
 
95
    RETURN res
96
END RelocCount;
97
 
98
 
99
PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; ver: INTEGER);
100
VAR
101
    File:  WR.FILE;
102
    exp:   BIN.EXPRT;
103
    n, i:  INTEGER;
104
 
105
    szversion: PE32.NAME;
106
 
107
    ImportTable: CHL.INTLIST;
108
    ILen, LibCount, isize:  INTEGER;
109
 
110
    ExpCount: INTEGER;
111
 
112
    icount, ecount, dcount, ccount: INTEGER;
113
 
114
    FileHeader: FH;
115
 
116
    flat, data, edata, idata, bss: SH;
117
 
118
 
119
    PROCEDURE ICount (ImportTable: CHL.INTLIST; ILen: INTEGER): INTEGER;
120
    VAR
121
        i, res: INTEGER;
122
 
123
    BEGIN
124
        res := 0;
125
 
126
        FOR i := 0 TO ILen - 1 DO
127
            IF CHL.GetInt(ImportTable, i) # 0 THEN
128
                INC(res)
129
            END
130
        END
131
 
132
        RETURN res
133
    END ICount;
134
 
135
 
136
    PROCEDURE SetNumberOfRelocations (VAR section: SH; NumberOfRelocations: INTEGER);
137
    BEGIN
138
        IF NumberOfRelocations >= 65536 THEN
7693 akron1 139
            ERRORS.Error(202)
7597 akron1 140
        END;
141
        section.NumberOfRelocations := WCHR(NumberOfRelocations)
142
    END SetNumberOfRelocations;
143
 
144
 
145
BEGIN
146
 
147
    szversion := "version";
148
 
149
    ASSERT(LENGTH(szversion) = 7);
150
 
151
    KOS.Import(program, 0, ImportTable, ILen, LibCount, isize);
152
    ExpCount := LISTS.count(program.exp_list);
153
 
154
    icount := CHL.Length(program.import);
155
    dcount := CHL.Length(program.data);
156
    ccount := CHL.Length(program.code);
157
    ecount := CHL.Length(program.export);
158
 
159
    FileHeader.Machine               :=  014CX;
160
    FileHeader.NumberOfSections      :=  5X;
161
    FileHeader.TimeDateStamp         :=  UTILS.UnixTime();
162
    //FileHeader.PointerToSymbolTable  :=  0;
163
    FileHeader.NumberOfSymbols       :=  6;
164
    FileHeader.SizeOfOptionalHeader  :=  0X;
165
    FileHeader.Characteristics       :=  0184X;
166
 
167
    flat.Name := ".flat";
168
    flat.VirtualSize := 0;
169
    flat.VirtualAddress := 0;
170
    flat.SizeOfRawData := ccount;
171
    flat.PointerToRawData := ORD(FileHeader.NumberOfSections) * PE32.SIZE_OF_IMAGE_SECTION_HEADER + PE32.SIZE_OF_IMAGE_FILE_HEADER;
172
    //flat.PointerToRelocations := 0;
173
    flat.PointerToLinenumbers := 0;
174
    SetNumberOfRelocations(flat, RelocCount(program));
175
    flat.NumberOfLinenumbers := 0X;
176
    flat.Characteristics := SHC_flat;
177
 
178
    data.Name := ".data";
179
    data.VirtualSize := 0;
180
    data.VirtualAddress := 0;
181
    data.SizeOfRawData := dcount;
182
    data.PointerToRawData := flat.PointerToRawData + flat.SizeOfRawData;
183
    data.PointerToRelocations := 0;
184
    data.PointerToLinenumbers := 0;
185
    data.NumberOfRelocations := 0X;
186
    data.NumberOfLinenumbers := 0X;
187
    data.Characteristics := SHC_data;
188
 
189
    edata.Name := ".edata";
190
    edata.VirtualSize := 0;
191
    edata.VirtualAddress := 0;
192
    edata.SizeOfRawData := ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD + LENGTH(szversion) + 1 + ecount;
193
    edata.PointerToRawData := data.PointerToRawData + data.SizeOfRawData;
194
    //edata.PointerToRelocations := 0;
195
    edata.PointerToLinenumbers := 0;
196
    SetNumberOfRelocations(edata, ExpCount * 2 + 1);
197
    edata.NumberOfLinenumbers := 0X;
198
    edata.Characteristics := SHC_data;
199
 
200
    idata.Name := ".idata";
201
    idata.VirtualSize := 0;
202
    idata.VirtualAddress := 0;
203
    idata.SizeOfRawData := isize;
204
    idata.PointerToRawData := edata.PointerToRawData + edata.SizeOfRawData;
205
    //idata.PointerToRelocations := 0;
206
    idata.PointerToLinenumbers := 0;
207
    SetNumberOfRelocations(idata, ICount(ImportTable, ILen));
208
    idata.NumberOfLinenumbers := 0X;
209
    idata.Characteristics := SHC_data;
210
 
211
    bss.Name := ".bss";
212
    bss.VirtualSize := 0;
213
    bss.VirtualAddress := 0;
214
    bss.SizeOfRawData := program.bss;
215
    bss.PointerToRawData := 0;
216
    bss.PointerToRelocations := 0;
217
    bss.PointerToLinenumbers := 0;
218
    bss.NumberOfRelocations := 0X;
219
    bss.NumberOfLinenumbers := 0X;
220
    bss.Characteristics := SHC_bss;
221
 
222
    flat.PointerToRelocations := idata.PointerToRawData + idata.SizeOfRawData;
223
    edata.PointerToRelocations := flat.PointerToRelocations + ORD(flat.NumberOfRelocations) * 10;
224
    idata.PointerToRelocations := edata.PointerToRelocations + ORD(edata.NumberOfRelocations) * 10;
225
 
226
    FileHeader.PointerToSymbolTable := idata.PointerToRelocations + ORD(idata.NumberOfRelocations) * 10;
227
 
228
    File := WR.Create(FileName);
229
 
230
    PE32.WriteFileHeader(File, FileHeader);
231
 
232
    PE32.WriteSectionHeader(File, flat);
233
    PE32.WriteSectionHeader(File, data);
234
    PE32.WriteSectionHeader(File, edata);
235
    PE32.WriteSectionHeader(File, idata);
236
    PE32.WriteSectionHeader(File, bss);
237
 
238
    CHL.WriteToFile(File, program.code);
239
    CHL.WriteToFile(File, program.data);
240
 
241
    exp := program.exp_list.first(BIN.EXPRT);
242
    WHILE exp # NIL DO
243
        WR.Write32LE(File, exp.nameoffs + edata.SizeOfRawData - ecount);
244
        WR.Write32LE(File, exp.label);
245
        exp := exp.next(BIN.EXPRT)
246
    END;
247
 
248
    WR.Write32LE(File, ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD);
249
    WR.Write32LE(File, ver);
250
 
251
    WR.Write32LE(File, 0);
252
 
253
    PE32.WriteName(File, szversion);
254
    CHL.WriteToFile(File, program.export);
255
 
256
    FOR i := 0 TO ILen - 1 DO
257
        WR.Write32LE(File, CHL.GetInt(ImportTable, i))
258
    END;
259
 
260
    CHL.WriteToFile(File, program.import);
261
 
262
    Reloc(program, File);
263
 
264
    n := 0;
265
    exp := program.exp_list.first(BIN.EXPRT);
266
    WHILE exp # NIL DO
267
        WriteReloc(File, n, 3, 6);
268
        INC(n, 4);
269
 
270
        WriteReloc(File, n, 1, 6);
271
        INC(n, 4);
272
 
273
        exp := exp.next(BIN.EXPRT)
274
    END;
275
 
276
    WriteReloc(File, n, 3, 6);
277
 
278
    i := 0;
279
    WHILE i < LibCount * 2 DO
280
        WriteReloc(File, i * SIZE_OF_DWORD, 4, 6);
281
        INC(i);
282
        WriteReloc(File, i * SIZE_OF_DWORD, 4, 6);
283
        INC(i)
284
    END;
285
 
286
    FOR i := LibCount * 2 TO ILen - 1 DO
287
        IF CHL.GetInt(ImportTable, i) # 0 THEN
288
            WriteReloc(File, i * SIZE_OF_DWORD, 4, 6)
289
        END
290
    END;
291
 
292
    PE32.WriteName(File, "EXPORTS");
293
    WriteReloc(File, 0, 3, 2);
294
 
295
    PE32.WriteName(File, ".flat");
296
    WriteReloc(File, 0, 1, 3);
297
 
298
    PE32.WriteName(File, ".data");
299
    WriteReloc(File, 0, 2, 3);
300
 
301
    PE32.WriteName(File, ".edata");
302
    WriteReloc(File, 0, 3, 3);
303
 
304
    PE32.WriteName(File, ".idata");
305
    WriteReloc(File, 0, 4, 3);
306
 
307
    PE32.WriteName(File, ".bss");
308
    WriteReloc(File, 0, 5, 3);
309
 
310
    WR.Write32LE(File, 4);
311
 
312
    WR.Close(File)
313
END write;
314
 
315
 
316
END MSCOFF.