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