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