Subversion Repositories Kolibri OS

Rev

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

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