1 #include "stdafx.h"
2 #include "Commands/CDirectiveFile.h"
3 #include "Core/Common.h"
4 #include "Util/FileClasses.h"
5 #include "Core/FileManager.h"
6
7 //
8 // CDirectiveFile
9 //
10
CDirectiveFile()11 CDirectiveFile::CDirectiveFile()
12 {
13 type = Type::Invalid;
14 file = nullptr;
15 }
16
initOpen(const std::wstring & fileName,int64_t memory)17 void CDirectiveFile::initOpen(const std::wstring& fileName, int64_t memory)
18 {
19 type = Type::Open;
20 std::wstring fullName = getFullPathName(fileName);
21
22 file = std::make_shared<GenericAssemblerFile>(fullName,memory,false);
23 g_fileManager->addFile(file);
24
25 updateSection(++Global.Section);
26 }
27
initCreate(const std::wstring & fileName,int64_t memory)28 void CDirectiveFile::initCreate(const std::wstring& fileName, int64_t memory)
29 {
30 type = Type::Create;
31 std::wstring fullName = getFullPathName(fileName);
32
33 file = std::make_shared<GenericAssemblerFile>(fullName,memory,true);
34 g_fileManager->addFile(file);
35
36 updateSection(++Global.Section);
37 }
38
initCopy(const std::wstring & inputName,const std::wstring & outputName,int64_t memory)39 void CDirectiveFile::initCopy(const std::wstring& inputName, const std::wstring& outputName, int64_t memory)
40 {
41 type = Type::Copy;
42 std::wstring fullInputName = getFullPathName(inputName);
43 std::wstring fullOutputName = getFullPathName(outputName);
44
45 file = std::make_shared<GenericAssemblerFile>(fullOutputName,fullInputName,memory);
46 g_fileManager->addFile(file);
47
48 updateSection(++Global.Section);
49 }
50
initClose()51 void CDirectiveFile::initClose()
52 {
53 type = Type::Close;
54 updateSection(++Global.Section);
55 }
56
Validate()57 bool CDirectiveFile::Validate()
58 {
59 virtualAddress = g_fileManager->getVirtualAddress();
60 Arch->NextSection();
61
62 switch (type)
63 {
64 case Type::Open:
65 case Type::Create:
66 case Type::Copy:
67 g_fileManager->openFile(file,true);
68 return false;
69 case Type::Close:
70 closeFile = g_fileManager->getOpenFile();
71 g_fileManager->closeFile();
72 return false;
73 case Type::Invalid:
74 break;
75 }
76
77 return false;
78 }
79
Encode() const80 void CDirectiveFile::Encode() const
81 {
82 switch (type)
83 {
84 case Type::Open:
85 case Type::Create:
86 case Type::Copy:
87 g_fileManager->openFile(file,false);
88 break;
89 case Type::Close:
90 g_fileManager->closeFile();
91 break;
92 case Type::Invalid:
93 // TODO: Assert?
94 break;
95 }
96 }
97
writeTempData(TempData & tempData) const98 void CDirectiveFile::writeTempData(TempData& tempData) const
99 {
100 std::wstring str;
101
102 switch (type)
103 {
104 case Type::Open:
105 str = formatString(L".open \"%s\",0x%08X",file->getFileName(),file->getOriginalHeaderSize());
106 break;
107 case Type::Create:
108 str = formatString(L".create \"%s\",0x%08X",file->getFileName(),file->getOriginalHeaderSize());
109 break;
110 case Type::Copy:
111 str = formatString(L".open \"%s\",\"%s\",0x%08X",file->getOriginalFileName(),
112 file->getFileName(),file->getOriginalHeaderSize());
113 break;
114 case Type::Close:
115 str = L".close";
116 break;
117 case Type::Invalid:
118 // TODO: Assert?
119 break;
120 }
121
122 tempData.writeLine(virtualAddress,str);
123 }
124
writeSymData(SymbolData & symData) const125 void CDirectiveFile::writeSymData(SymbolData& symData) const
126 {
127 switch (type)
128 {
129 case Type::Open:
130 case Type::Create:
131 case Type::Copy:
132 file->beginSymData(symData);
133 break;
134 case Type::Close:
135 if (closeFile)
136 closeFile->endSymData(symData);
137 break;
138 case Type::Invalid:
139 // TODO: Assert?
140 break;
141 }
142 }
143
144 //
145 // CDirectivePosition
146 //
147
CDirectivePosition(Expression expression,Type type)148 CDirectivePosition::CDirectivePosition(Expression expression, Type type)
149 : expression(expression), type(type)
150 {
151 updateSection(++Global.Section);
152 }
153
exec() const154 void CDirectivePosition::exec() const
155 {
156 switch (type)
157 {
158 case Physical:
159 g_fileManager->seekPhysical(position);
160 break;
161 case Virtual:
162 g_fileManager->seekVirtual(position);
163 break;
164 }
165 }
166
Validate()167 bool CDirectivePosition::Validate()
168 {
169 virtualAddress = g_fileManager->getVirtualAddress();
170
171 if (expression.evaluateInteger(position) == false)
172 {
173 Logger::queueError(Logger::FatalError,L"Invalid position");
174 return false;
175 }
176
177 Arch->NextSection();
178 exec();
179 return false;
180 }
181
Encode() const182 void CDirectivePosition::Encode() const
183 {
184 Arch->NextSection();
185 exec();
186 }
187
writeTempData(TempData & tempData) const188 void CDirectivePosition::writeTempData(TempData& tempData) const
189 {
190 switch (type)
191 {
192 case Physical:
193 tempData.writeLine(virtualAddress,formatString(L".orga 0x%08X",position));
194 break;
195 case Virtual:
196 tempData.writeLine(virtualAddress,formatString(L".org 0x%08X",position));
197 break;
198 }
199 }
200
201 //
202 // CDirectiveIncbin
203 //
204
CDirectiveIncbin(const std::wstring & fileName)205 CDirectiveIncbin::CDirectiveIncbin(const std::wstring& fileName)
206 : size(0), start(0)
207 {
208 this->fileName = getFullPathName(fileName);
209
210 if (fileExists(this->fileName) == false)
211 {
212 Logger::printError(Logger::FatalError,L"File %s not found",this->fileName);
213 }
214
215 this->fileSize = ::fileSize(this->fileName);
216 }
217
Validate()218 bool CDirectiveIncbin::Validate()
219 {
220 virtualAddress = g_fileManager->getVirtualAddress();
221
222 if (startExpression.isLoaded())
223 {
224 if (startExpression.evaluateInteger(start) == false)
225 {
226 Logger::queueError(Logger::Error,L"Invalid position expression");
227 return false;
228 }
229
230 if (start > fileSize)
231 {
232 Logger::queueError(Logger::Error,L"Start position past end of file");
233 return false;
234 }
235 } else {
236 start = 0;
237 }
238
239 if (sizeExpression.isLoaded())
240 {
241 if (sizeExpression.evaluateInteger(size) == false)
242 {
243 Logger::queueError(Logger::Error,L"Invalid size expression");
244 return false;
245 }
246 } else {
247 size = fileSize-start;
248 }
249
250 if (start+size > fileSize)
251 {
252 Logger::queueError(Logger::Warning,L"Read size truncated due to file size");
253 size = fileSize-start;
254 }
255
256 Arch->NextSection();
257 g_fileManager->advanceMemory(size);
258 return false;
259 }
260
Encode() const261 void CDirectiveIncbin::Encode() const
262 {
263 if (size != 0)
264 {
265 ByteArray data = ByteArray::fromFile(fileName,(long)start,size);
266 if ((int) data.size() != size)
267 {
268 Logger::printError(Logger::Error,L"Could not read file \"%s\"",fileName);
269 return;
270 }
271 g_fileManager->write(data.data(),data.size());
272 }
273 }
274
writeTempData(TempData & tempData) const275 void CDirectiveIncbin::writeTempData(TempData& tempData) const
276 {
277 tempData.writeLine(virtualAddress,formatString(L".incbin \"%s\"",fileName));
278 }
279
writeSymData(SymbolData & symData) const280 void CDirectiveIncbin::writeSymData(SymbolData& symData) const
281 {
282 symData.addData(virtualAddress,size,SymbolData::Data8);
283 }
284
285
286 //
287 // CDirectiveAlignFill
288 //
289
CDirectiveAlignFill(int64_t value,Mode mode)290 CDirectiveAlignFill::CDirectiveAlignFill(int64_t value, Mode mode)
291 {
292 this->mode = mode;
293 this->value = value;
294 this->finalSize = 0;
295 this->fillByte = 0;
296 }
297
CDirectiveAlignFill(Expression & value,Mode mode)298 CDirectiveAlignFill::CDirectiveAlignFill(Expression& value, Mode mode)
299 : CDirectiveAlignFill(0,mode)
300 {
301 valueExpression = value;
302 }
303
CDirectiveAlignFill(Expression & value,Expression & fillValue,Mode mode)304 CDirectiveAlignFill::CDirectiveAlignFill(Expression& value, Expression& fillValue, Mode mode)
305 : CDirectiveAlignFill(value,mode)
306 {
307 fillExpression = fillValue;
308 }
309
Validate()310 bool CDirectiveAlignFill::Validate()
311 {
312 virtualAddress = g_fileManager->getVirtualAddress();
313
314 if (valueExpression.isLoaded())
315 {
316 if (valueExpression.evaluateInteger(value) == false)
317 {
318 Logger::queueError(Logger::FatalError,L"Invalid %s",mode == Fill ? L"size" : L"alignment");
319 return false;
320 }
321 }
322
323 int64_t oldSize = finalSize;
324 int64_t mod;
325 switch (mode)
326 {
327 case Align:
328 if (isPowerOfTwo(value) == false)
329 {
330 Logger::queueError(Logger::Error,L"Invalid alignment %d",value);
331 return false;
332 }
333
334 mod = g_fileManager->getVirtualAddress() % value;
335 finalSize = mod ? value-mod : 0;
336 break;
337 case Fill:
338 finalSize = value;
339 break;
340 }
341
342 if (fillExpression.isLoaded())
343 {
344 if (fillExpression.evaluateInteger(fillByte) == false)
345 {
346 Logger::printError(Logger::FatalError,L"Invalid fill value");
347 return false;
348 }
349 }
350
351 Arch->NextSection();
352 g_fileManager->advanceMemory(finalSize);
353
354 bool result = oldSize != finalSize;
355 oldSize = finalSize;
356 return result;
357 }
358
Encode() const359 void CDirectiveAlignFill::Encode() const
360 {
361 unsigned char buffer[128];
362 int64_t n = finalSize;
363
364 memset(buffer,fillByte,n > 128 ? 128 : n);
365 while (n > 128)
366 {
367 g_fileManager->write(buffer,128);
368 n -= 128;
369 }
370
371 g_fileManager->write(buffer,n);
372 }
373
writeTempData(TempData & tempData) const374 void CDirectiveAlignFill::writeTempData(TempData& tempData) const
375 {
376 switch (mode)
377 {
378 case Align:
379 tempData.writeLine(virtualAddress,formatString(L".align 0x%08X",value));
380 break;
381 case Fill:
382 tempData.writeLine(virtualAddress,formatString(L".fill 0x%08X,0x%02X",value,fillByte));
383 break;
384 }
385 }
386
writeSymData(SymbolData & symData) const387 void CDirectiveAlignFill::writeSymData(SymbolData& symData) const
388 {
389 switch (mode)
390 {
391 case Align: // ?
392 break;
393 case Fill:
394 symData.addData(virtualAddress,value,SymbolData::Data8);
395 break;
396 }
397 }
398
399 //
400 // CDirectiveSkip
401 //
402
CDirectiveSkip(Expression & expression)403 CDirectiveSkip::CDirectiveSkip(Expression& expression)
404 : expression(expression) {}
405
Validate()406 bool CDirectiveSkip::Validate()
407 {
408 virtualAddress = g_fileManager->getVirtualAddress();
409
410 if (expression.isLoaded())
411 {
412 if (expression.evaluateInteger(value) == false)
413 {
414 Logger::queueError(Logger::FatalError,L"Invalid skip length");
415 return false;
416 }
417 }
418
419 Arch->NextSection();
420 g_fileManager->advanceMemory(value);
421
422 return false;
423 }
424
Encode() const425 void CDirectiveSkip::Encode() const
426 {
427 Arch->NextSection();
428 g_fileManager->advanceMemory(value);
429 }
430
writeTempData(TempData & tempData) const431 void CDirectiveSkip::writeTempData(TempData& tempData) const
432 {
433 tempData.writeLine(virtualAddress,formatString(L".skip 0x%08X",value));
434 }
435
436 //
437 // CDirectiveHeaderSize
438 //
439
CDirectiveHeaderSize(Expression expression)440 CDirectiveHeaderSize::CDirectiveHeaderSize(Expression expression)
441 : expression(expression) {}
442
exec() const443 void CDirectiveHeaderSize::exec() const
444 {
445 std::shared_ptr<AssemblerFile> openFile = g_fileManager->getOpenFile();
446 if (!openFile->hasFixedVirtualAddress())
447 {
448 Logger::printError(Logger::Error,L"Header size not applicable for this file");
449 return;
450 }
451 std::shared_ptr<GenericAssemblerFile> file = std::static_pointer_cast<GenericAssemblerFile>(openFile);
452 int64_t physicalAddress = file->getPhysicalAddress();
453 file->setHeaderSize(headerSize);
454 file->seekPhysical(physicalAddress);
455 }
456
Validate()457 bool CDirectiveHeaderSize::Validate()
458 {
459 virtualAddress = g_fileManager->getVirtualAddress();
460
461 if (expression.evaluateInteger(headerSize) == false)
462 {
463 Logger::queueError(Logger::FatalError,L"Invalid header size");
464 return false;
465 }
466
467 exec();
468 return false;
469 }
470
Encode() const471 void CDirectiveHeaderSize::Encode() const
472 {
473 exec();
474 }
475
writeTempData(TempData & tempData) const476 void CDirectiveHeaderSize::writeTempData(TempData& tempData) const
477 {
478 tempData.writeLine(virtualAddress,formatString(L".headersize %s0x%08X",
479 headerSize < 0 ? L"-" : L"", headerSize < 0 ? -headerSize : headerSize));
480 }
481
482
483 //
484 // DirectiveObjImport
485 //
486
DirectiveObjImport(const std::wstring & inputName)487 DirectiveObjImport::DirectiveObjImport(const std::wstring& inputName)
488 {
489 ctor = nullptr;
490 if (rel.init(inputName))
491 {
492 rel.exportSymbols();
493 }
494 }
495
DirectiveObjImport(const std::wstring & inputName,const std::wstring & ctorName)496 DirectiveObjImport::DirectiveObjImport(const std::wstring& inputName, const std::wstring& ctorName)
497 {
498 if (rel.init(inputName))
499 {
500 rel.exportSymbols();
501 ctor = rel.generateCtor(ctorName);
502 }
503 }
504
Validate()505 bool DirectiveObjImport::Validate()
506 {
507 bool result = false;
508 if (ctor != nullptr && ctor->Validate())
509 result = true;
510
511 int64_t memory = g_fileManager->getVirtualAddress();
512 rel.relocate(memory);
513 g_fileManager->advanceMemory((size_t)memory);
514
515 return rel.hasDataChanged() || result;
516 }
517
Encode() const518 void DirectiveObjImport::Encode() const
519 {
520 if (ctor != nullptr)
521 ctor->Encode();
522
523 const ByteArray& data = rel.getData();
524 g_fileManager->write(data.data(),data.size());
525 }
526
writeTempData(TempData & tempData) const527 void DirectiveObjImport::writeTempData(TempData& tempData) const
528 {
529 if (ctor != nullptr)
530 ctor->writeTempData(tempData);
531 }
532
writeSymData(SymbolData & symData) const533 void DirectiveObjImport::writeSymData(SymbolData& symData) const
534 {
535 if (ctor != nullptr)
536 ctor->writeSymData(symData);
537
538 rel.writeSymbols(symData);
539 }
540