Subversion Repositories Kolibri OS

Rev

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