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.> |