1/*
2 * File:	ConversionController.cpp
3 *
4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5 * See included license file for license details.
6 */
7
8#include "ConversionController.h"
9#include <stdexcept>
10#include "EvalContext.h"
11#include "ElftosbErrors.h"
12#include "GlobMatcher.h"
13#include "ExcludesListMatcher.h"
14#include "BootImageGenerator.h"
15#include "EncoreBootImageGenerator.h"
16#include "Logging.h"
17#include "OptionDictionary.h"
18#include "format_string.h"
19#include "SearchPath.h"
20#include "DataSourceImager.h"
21#include "IVTDataSource.h"
22#include <algorithm>
23
24//! Set to 1 to cause the ConversionController to print information about
25//! the values that it processes (options, constants, etc.).
26#define PRINT_VALUES 1
27
28using namespace elftosb;
29
30// Define the parser function prototype;
31extern int yyparse(ElftosbLexer * lexer, CommandFileASTNode ** resultAST);
32
33bool elftosb::g_enableHABSupport = false;
34
35ConversionController::ConversionController()
36:	OptionDictionary(),
37	m_commandFilePath(),
38	m_ast(),
39	m_defaultSource(0)
40{
41	m_context.setSourceFileManager(this);
42}
43
44ConversionController::~ConversionController()
45{
46	// clean up sources
47	source_map_t::iterator it = m_sources.begin();
48	for (; it != m_sources.end(); ++it)
49	{
50		if (it->second)
51		{
52			delete it->second;
53		}
54	}
55}
56
57void ConversionController::setCommandFilePath(const std::string & path)
58{
59	m_commandFilePath = new std::string(path);
60}
61
62//! The paths provided to this method are added to an array and accessed with the
63//! "extern(N)" notation in the command file. So the path provided in the third
64//! call to addExternalFilePath() will be found with N=2 in the source definition.
65void ConversionController::addExternalFilePath(const std::string & path)
66{
67	m_externPaths.push_back(path);
68}
69
70bool ConversionController::hasSourceFile(const std::string & name)
71{
72	return m_sources.find(name) != m_sources.end();
73}
74
75SourceFile * ConversionController::getSourceFile(const std::string & name)
76{
77	if (!hasSourceFile(name))
78	{
79		return NULL;
80	}
81
82	return m_sources[name];
83}
84
85SourceFile * ConversionController::getDefaultSourceFile()
86{
87	return m_defaultSource;
88}
89
90//! These steps are executed while running this method:
91//!		- The command file is parsed into an abstract syntax tree.
92//!		- The list of options is extracted.
93//!		- Constant expressions are evaluated.
94//!		- The list of source files is extracted and source file objects created.
95//!		- Section definitions are extracted.
96//!
97//! This method does not produce any output. It processes the input files and
98//! builds a representation of the output in memory. Use the generateOutput() method
99//! to produce a BootImage object after this method returns.
100//!
101//! \note This method is \e not reentrant. And in fact, the whole class is not designed
102//!		to be reentrant.
103//!
104//! \exception std::runtime_error Any number of problems will cause this exception to
105//!		be thrown.
106//!
107//! \see parseCommandFile()
108//! \see processOptions()
109//! \see processConstants()
110//! \see processSources()
111//! \see processSections()
112void ConversionController::run()
113{
114#if PRINT_VALUES
115	Log::SetOutputLevel debugLevel(Logger::DEBUG2);
116#endif
117
118	parseCommandFile();
119	assert(m_ast);
120
121	ListASTNode * blocks = m_ast->getBlocks();
122	if (!blocks)
123	{
124		throw std::runtime_error("command file has no blocks");
125	}
126
127	ListASTNode::iterator it = blocks->begin();
128	for (; it != blocks->end(); ++it)
129	{
130		ASTNode * node = *it;
131
132		// Handle an options block.
133		OptionsBlockASTNode * options = dynamic_cast<OptionsBlockASTNode *>(node);
134		if (options)
135		{
136			processOptions(options->getOptions());
137			continue;
138		}
139
140		// Handle a constants block.
141		ConstantsBlockASTNode * constants = dynamic_cast<ConstantsBlockASTNode *>(node);
142		if (constants)
143		{
144			processConstants(constants->getConstants());
145			continue;
146		}
147
148		// Handle a sources block.
149		SourcesBlockASTNode * sources = dynamic_cast<SourcesBlockASTNode *>(node);
150		if (sources)
151		{
152			processSources(sources->getSources());
153		}
154	}
155
156	processSections(m_ast->getSections());
157}
158
159//! Opens the command file and runs it through the lexer and parser. The resulting
160//! abstract syntax tree is held in the m_ast member variable. After parsing, the
161//! command file is closed.
162//!
163//! \exception std::runtime_error Several problems will cause this exception to be
164//!		raised, including an unspecified command file path or an error opening the
165//!		file.
166void ConversionController::parseCommandFile()
167{
168	if (!m_commandFilePath)
169	{
170		throw std::runtime_error("no command file path was provided");
171	}
172
173	// Search for command file
174	std::string actualPath;
175	bool found = PathSearcher::getGlobalSearcher().search(*m_commandFilePath, PathSearcher::kFindFile, true, actualPath);
176	if (!found)
177	{
178		throw runtime_error(format_string("unable to find command file %s\n", m_commandFilePath->c_str()));
179	}
180
181	// open command file
182	std::ifstream commandFile(actualPath.c_str(), ios_base::in | ios_base::binary);
183	if (!commandFile.is_open())
184	{
185		throw std::runtime_error("could not open command file");
186	}
187
188	try
189	{
190		// create lexer instance
191		ElftosbLexer lexer(commandFile);
192//		testLexer(lexer);
193
194		CommandFileASTNode * ast = NULL;
195		int result = yyparse(&lexer, &ast);
196		m_ast = ast;
197
198		// check results
199		if (result || !m_ast)
200		{
201			throw std::runtime_error("failed to parse command file");
202		}
203
204		// dump AST
205//		m_ast->printTree(0);
206
207		// close command file
208		commandFile.close();
209	}
210	catch (...)
211	{
212		// close command file
213		commandFile.close();
214
215		// rethrow exception
216		throw;
217	}
218}
219
220//! Iterates over the option definition AST nodes. elftosb::Value objects are created for
221//! each option value and added to the option dictionary.
222//!
223//! \exception std::runtime_error Various errors will cause this exception to be thrown. These
224//!		include AST nodes being an unexpected type or expression not evaluating to integers.
225void ConversionController::processOptions(ListASTNode * options)
226{
227	if (!options)
228	{
229		return;
230	}
231
232	ListASTNode::iterator it = options->begin();
233	for (; it != options->end(); ++it)
234	{
235		std::string ident;
236		Value * value = convertAssignmentNodeToValue(*it, ident);
237
238		// check if this option has already been set
239		if (hasOption(ident))
240		{
241			throw semantic_error(format_string("line %d: option already set", (*it)->getFirstLine()));
242		}
243
244		// now save the option value in our map
245		if (value)
246		{
247			setOption(ident, value);
248		}
249	}
250}
251
252//! Scans the constant definition AST nodes, evaluates expression nodes by calling their
253//! elftosb::ExprASTNode::reduce() method, and updates the evaluation context member so
254//! those constant values can be used in other expressions.
255//!
256//! \exception std::runtime_error Various errors will cause this exception to be thrown. These
257//!		include AST nodes being an unexpected type or expression not evaluating to integers.
258void ConversionController::processConstants(ListASTNode * constants)
259{
260	if (!constants)
261	{
262		return;
263	}
264
265	ListASTNode::iterator it = constants->begin();
266	for (; it != constants->end(); ++it)
267	{
268		std::string ident;
269		Value * value = convertAssignmentNodeToValue(*it, ident);
270
271		SizedIntegerValue * intValue = dynamic_cast<SizedIntegerValue*>(value);
272		if (!intValue)
273		{
274			throw semantic_error(format_string("line %d: constant value is an invalid type", (*it)->getFirstLine()));
275		}
276
277//#if PRINT_VALUES
278//		Log::log("constant ");
279//		printIntConstExpr(ident, intValue);
280//#endif
281
282		// record this constant's value in the evaluation context
283		m_context.setVariable(ident, intValue->getValue(), intValue->getWordSize());
284	}
285}
286
287//! \exception std::runtime_error Various errors will cause this exception to be thrown. These
288//!		include AST nodes being an unexpected type or expression not evaluating to integers.
289//!
290//! \todo Handle freeing of dict if an exception occurs.
291void ConversionController::processSources(ListASTNode * sources)
292{
293	if (!sources)
294	{
295		return;
296	}
297
298	ListASTNode::iterator it = sources->begin();
299	for (; it != sources->end(); ++it)
300	{
301		SourceDefASTNode * node = dynamic_cast<SourceDefASTNode*>(*it);
302		if (!node)
303		{
304			throw semantic_error(format_string("line %d: source definition node is an unexpected type", node->getFirstLine()));
305		}
306
307		// get source name and check if it has already been defined
308		std::string * name = node->getName();
309		if (m_sources.find(*name) != m_sources.end())
310		{
311			// can't define a source multiple times
312			throw semantic_error(format_string("line %d: source already defined", node->getFirstLine()));
313		}
314
315		// convert attributes into an option dict
316		OptionDictionary * dict = new OptionDictionary(this);
317		ListASTNode * attrsNode = node->getAttributes();
318		if (attrsNode)
319		{
320			ListASTNode::iterator attrIt = attrsNode->begin();
321			for (; attrIt != attrsNode->end(); ++attrIt)
322			{
323				std::string ident;
324				Value * value = convertAssignmentNodeToValue(*attrIt, ident);
325				dict->setOption(ident, value);
326			}
327		}
328
329		// figure out which type of source definition this is
330		PathSourceDefASTNode * pathNode = dynamic_cast<PathSourceDefASTNode*>(node);
331		ExternSourceDefASTNode * externNode = dynamic_cast<ExternSourceDefASTNode*>(node);
332		SourceFile * file = NULL;
333
334		if (pathNode)
335		{
336			// explicit path
337			std::string * path = pathNode->getPath();
338
339#if PRINT_VALUES
340			Log::log("source %s => path(%s)\n", name->c_str(), path->c_str());
341#endif
342
343			try
344			{
345				file = SourceFile::openFile(*path);
346			}
347			catch (...)
348			{
349				// file doesn't exist
350				Log::log(Logger::INFO2, "failed to open source file: %s (ignoring for now)\n", path->c_str());
351				m_failedSources.push_back(*name);
352			}
353		}
354		else if (externNode)
355		{
356			// externally provided path
357			ExprASTNode * expr = externNode->getSourceNumberExpr()->reduce(m_context);
358			IntConstExprASTNode * intConst = dynamic_cast<IntConstExprASTNode*>(expr);
359			if (!intConst)
360			{
361				throw semantic_error(format_string("line %d: expression didn't evaluate to an integer", expr->getFirstLine()));
362			}
363
364			uint32_t externalFileNumber = static_cast<uint32_t>(intConst->getValue());
365
366			// make sure the extern number is valid
367			if (externalFileNumber >= 0 && externalFileNumber < m_externPaths.size())
368			{
369
370#if PRINT_VALUES
371			Log::log("source %s => extern(%d=%s)\n", name->c_str(), externalFileNumber, m_externPaths[externalFileNumber].c_str());
372#endif
373
374				try
375				{
376					file = SourceFile::openFile(m_externPaths[externalFileNumber]);
377				}
378				catch (...)
379				{
380					Log::log(Logger::INFO2, "failed to open source file: %s (ignoring for now)\n", m_externPaths[externalFileNumber].c_str());
381					m_failedSources.push_back(*name);
382				}
383			}
384		}
385		else
386		{
387			throw semantic_error(format_string("line %d: unexpected source definition node type", node->getFirstLine()));
388		}
389
390		if (file)
391		{
392			// set options
393			file->setOptions(dict);
394
395			// stick the file object in the source map
396			m_sources[*name] = file;
397		}
398	}
399}
400
401void ConversionController::processSections(ListASTNode * sections)
402{
403	if (!sections)
404	{
405		Log::log(Logger::WARNING, "warning: no sections were defined in command file");
406		return;
407	}
408
409	ListASTNode::iterator it = sections->begin();
410	for (; it != sections->end(); ++it)
411	{
412		SectionContentsASTNode * node = dynamic_cast<SectionContentsASTNode*>(*it);
413		if (!node)
414		{
415			throw semantic_error(format_string("line %d: section definition is unexpected type", node->getFirstLine()));
416		}
417
418		// evaluate section number
419		ExprASTNode * idExpr = node->getSectionNumberExpr()->reduce(m_context);
420		IntConstExprASTNode * idConst = dynamic_cast<IntConstExprASTNode*>(idExpr);
421		if (!idConst)
422		{
423			throw semantic_error(format_string("line %d: section number did not evaluate to an integer", idExpr->getFirstLine()));
424		}
425		uint32_t sectionID = idConst->getValue();
426
427		// Create options context for this section. The options context has the
428		// conversion controller as its parent context so it will inherit global options.
429		// The context will be set in the section after the section is created below.
430		OptionDictionary * optionsDict = new OptionDictionary(this);
431		ListASTNode * attrsNode = node->getOptions();
432		if (attrsNode)
433		{
434			ListASTNode::iterator attrIt = attrsNode->begin();
435			for (; attrIt != attrsNode->end(); ++attrIt)
436			{
437				std::string ident;
438				Value * value = convertAssignmentNodeToValue(*attrIt, ident);
439				optionsDict->setOption(ident, value);
440			}
441		}
442
443		// Now create the actual section object based on its type.
444		OutputSection * outputSection = NULL;
445		BootableSectionContentsASTNode * bootableSection;
446		DataSectionContentsASTNode * dataSection;
447		if (bootableSection = dynamic_cast<BootableSectionContentsASTNode*>(node))
448		{
449			// process statements into a sequence of operations
450			ListASTNode * statements = bootableSection->getStatements();
451			OperationSequence * sequence = convertStatementList(statements);
452
453#if 0
454			Log::log("section ID = %d\n", sectionID);
455			statements->printTree(0);
456
457			Log::log("sequence has %d operations\n", sequence->getCount());
458			OperationSequence::iterator_t it = sequence->begin();
459			for (; it != sequence->end(); ++it)
460			{
461				Operation * op = *it;
462				Log::log("op = %p\n", op);
463			}
464#endif
465
466			// create the output section and add it to the list
467			OperationSequenceSection * opSection = new OperationSequenceSection(sectionID);
468			opSection->setOptions(optionsDict);
469			opSection->getSequence() += sequence;
470			outputSection = opSection;
471		}
472		else if (dataSection = dynamic_cast<DataSectionContentsASTNode*>(node))
473		{
474			outputSection = convertDataSection(dataSection, sectionID, optionsDict);
475		}
476		else
477		{
478			throw semantic_error(format_string("line %d: unexpected section contents type", node->getFirstLine()));
479		}
480
481		if (outputSection)
482		{
483			m_outputSections.push_back(outputSection);
484		}
485	}
486}
487
488//! Creates an instance of BinaryDataSection from the AST node passed in the
489//! \a dataSection parameter. The section-specific options for this node will
490//! have already been converted into an OptionDictionary, the one passed in
491//! the \a optionsDict parameter.
492//!
493//! The \a dataSection node will have as its contents one of the AST node
494//! classes that represents a source of data. The member function
495//! createSourceFromNode() is used to convert this AST node into an
496//! instance of a DataSource subclass. Then the method imageDataSource()
497//! converts the segments of the DataSource into a raw binary buffer that
498//! becomes the contents of the BinaryDataSection this is returned.
499//!
500//! \param dataSection The AST node for the data section.
501//! \param sectionID Unique tag value the user has assigned to this section.
502//! \param optionsDict Options that apply only to this section. This dictionary
503//!		will be assigned as the options dictionary for the resulting section
504//!		object. Its parent is the conversion controller itself.
505//! \return An instance of BinaryDataSection. Its contents are a contiguous
506//!		binary representation of the contents of \a dataSection.
507OutputSection * ConversionController::convertDataSection(DataSectionContentsASTNode * dataSection, uint32_t sectionID, OptionDictionary * optionsDict)
508{
509	// Create a data source from the section contents AST node.
510	ASTNode * contents = dataSection->getContents();
511	DataSource * dataSource = createSourceFromNode(contents);
512
513	// Convert the data source to a raw buffer.
514	DataSourceImager imager;
515	imager.addDataSource(dataSource);
516
517	// Then make a data section from the buffer.
518	BinaryDataSection * resultSection = new BinaryDataSection(sectionID);
519	resultSection->setOptions(optionsDict);
520	if (imager.getLength())
521	{
522		resultSection->setData(imager.getData(), imager.getLength());
523	}
524
525	return resultSection;
526}
527
528//! @param node The AST node instance for the assignment expression.
529//! @param[out] ident Upon exit this string will be set the the left hand side of the
530//!		assignment expression, the identifier name.
531//!
532//! @return An object that is a subclass of Value is returned. The specific subclass will
533//!		depend on the type of the right hand side of the assignment expression whose AST
534//!		node was provided in the @a node argument.
535//!
536//! @exception semantic_error Thrown for any error where an AST node is an unexpected type.
537//!		This may be the @a node argument itself, if it is not an AssignmentASTNode. Or it
538//!		may be an unexpected type for either the right or left hand side of the assignment.
539//!		The message for the exception will contain a description of the error.
540Value * ConversionController::convertAssignmentNodeToValue(ASTNode * node, std::string & ident)
541{
542	Value * resultValue = NULL;
543
544	// each item of the options list should be an assignment node
545	AssignmentASTNode * assignmentNode = dynamic_cast<AssignmentASTNode*>(node);
546	if (!node)
547	{
548		throw semantic_error(format_string("line %d: node is wrong type", assignmentNode->getFirstLine()));
549	}
550
551	// save the left hand side (the identifier) into ident
552	ident = *assignmentNode->getIdent();
553
554	// get the right hand side and convert it to a Value instance
555	ASTNode * valueNode = assignmentNode->getValue();
556	StringConstASTNode * str;
557	ExprASTNode * expr;
558	if (str = dynamic_cast<StringConstASTNode*>(valueNode))
559	{
560		// the option value is a string constant
561		resultValue = new StringValue(str->getString());
562
563//#if PRINT_VALUES
564//		Log::log("option %s => \'%s\'\n", ident->c_str(), str->getString()->c_str());
565//#endif
566	}
567	else if (expr = dynamic_cast<ExprASTNode*>(valueNode))
568	{
569		ExprASTNode * reducedExpr = expr->reduce(m_context);
570		IntConstExprASTNode * intConst = dynamic_cast<IntConstExprASTNode*>(reducedExpr);
571		if (!intConst)
572		{
573			throw semantic_error(format_string("line %d: expression didn't evaluate to an integer", expr->getFirstLine()));
574		}
575
576//#if PRINT_VALUES
577//		Log::log("option ");
578//		printIntConstExpr(*ident, intConst);
579//#endif
580
581		resultValue = new SizedIntegerValue(intConst->getValue(), intConst->getSize());
582	}
583	else
584	{
585		throw semantic_error(format_string("line %d: right hand side node is an unexpected type", valueNode->getFirstLine()));
586	}
587
588	return resultValue;
589}
590
591//! Builds up a sequence of Operation objects that are equivalent to the
592//! statements in the \a statements list. The statement list is simply iterated
593//! over and the results of convertOneStatement() are used to build up
594//! the final result sequence.
595//!
596//! \see convertOneStatement()
597OperationSequence * ConversionController::convertStatementList(ListASTNode * statements)
598{
599	OperationSequence * resultSequence = new OperationSequence();
600	ListASTNode::iterator it = statements->begin();
601	for (; it != statements->end(); ++it)
602	{
603		StatementASTNode * statement = dynamic_cast<StatementASTNode*>(*it);
604		if (!statement)
605		{
606			throw semantic_error(format_string("line %d: statement node is unexpected type", (*it)->getFirstLine()));
607		}
608
609		// convert this statement and append it to the result
610		OperationSequence * sequence = convertOneStatement(statement);
611		if (sequence)
612		{
613			*resultSequence += sequence;
614		}
615	}
616
617	return resultSequence;
618}
619
620//! Uses C++ RTTI to identify the particular subclass of StatementASTNode that
621//! the \a statement argument matches. Then the appropriate conversion method
622//! is called.
623//!
624//! \see convertLoadStatement()
625//! \see convertCallStatement()
626//! \see convertFromStatement()
627OperationSequence * ConversionController::convertOneStatement(StatementASTNode * statement)
628{
629	// see if it's a load statement
630	LoadStatementASTNode * load = dynamic_cast<LoadStatementASTNode*>(statement);
631	if (load)
632	{
633		return convertLoadStatement(load);
634	}
635
636	// see if it's a call statement
637	CallStatementASTNode * call = dynamic_cast<CallStatementASTNode*>(statement);
638	if (call)
639	{
640		return convertCallStatement(call);
641	}
642
643	// see if it's a from statement
644	FromStatementASTNode * from = dynamic_cast<FromStatementASTNode*>(statement);
645	if (from)
646	{
647		return convertFromStatement(from);
648	}
649
650	// see if it's a mode statement
651	ModeStatementASTNode * mode = dynamic_cast<ModeStatementASTNode*>(statement);
652	if (mode)
653	{
654		return convertModeStatement(mode);
655	}
656
657	// see if it's an if statement
658	IfStatementASTNode * ifStmt = dynamic_cast<IfStatementASTNode*>(statement);
659	if (ifStmt)
660	{
661		return convertIfStatement(ifStmt);
662	}
663
664	// see if it's a message statement
665	MessageStatementASTNode * messageStmt = dynamic_cast<MessageStatementASTNode*>(statement);
666	if (messageStmt)
667	{
668		// Message statements don't produce operation sequences.
669		handleMessageStatement(messageStmt);
670		return NULL;
671	}
672
673	// didn't match any of the expected statement types
674	throw semantic_error(format_string("line %d: unexpected statement type", statement->getFirstLine()));
675	return NULL;
676}
677
678//! Possible load data node types:
679//! - StringConstASTNode
680//! - ExprASTNode
681//! - SourceASTNode
682//! - SectionMatchListASTNode
683//!
684//! Possible load target node types:
685//! - SymbolASTNode
686//! - NaturalLocationASTNode
687//! - AddressRangeASTNode
688OperationSequence * ConversionController::convertLoadStatement(LoadStatementASTNode * statement)
689{
690	LoadOperation * op = NULL;
691
692	try
693	{
694		// build load operation from source and target
695		op = new LoadOperation();
696		op->setSource(createSourceFromNode(statement->getData()));
697		op->setTarget(createTargetFromNode(statement->getTarget()));
698		op->setDCDLoad(statement->isDCDLoad());
699
700		return new OperationSequence(op);
701	}
702	catch (...)
703	{
704		if (op)
705		{
706			delete op;
707		}
708		throw;
709	}
710}
711
712//! Possible call target node types:
713//! - SymbolASTNode
714//! - ExprASTNode
715//!
716//! Possible call argument node types:
717//! - ExprASTNode
718//! - NULL
719OperationSequence * ConversionController::convertCallStatement(CallStatementASTNode * statement)
720{
721	ExecuteOperation * op = NULL;
722
723	try
724	{
725		// create operation from AST nodes
726		op = new ExecuteOperation();
727
728		bool isHAB = statement->isHAB();
729
730		op->setTarget(createTargetFromNode(statement->getTarget()));
731
732		// set argument value, which defaults to 0 if no expression was provided
733		uint32_t arg = 0;
734		ASTNode * argNode = statement->getArgument();
735		if (argNode)
736		{
737			ExprASTNode * argExprNode = dynamic_cast<ExprASTNode*>(argNode);
738			if (!argExprNode)
739			{
740				throw semantic_error(format_string("line %d: call argument is unexpected type", argNode->getFirstLine()));
741			}
742			argExprNode = argExprNode->reduce(m_context);
743			IntConstExprASTNode * intNode = dynamic_cast<IntConstExprASTNode*>(argExprNode);
744			if (!intNode)
745			{
746				throw semantic_error(format_string("line %d: call argument did not evaluate to an integer", argExprNode->getFirstLine()));
747			}
748
749			arg = intNode->getValue();
750		}
751		op->setArgument(arg);
752
753		// set call type
754		switch (statement->getCallType())
755		{
756			case CallStatementASTNode::kCallType:
757				op->setExecuteType(ExecuteOperation::kCall);
758				break;
759			case CallStatementASTNode::kJumpType:
760				op->setExecuteType(ExecuteOperation::kJump);
761				break;
762		}
763
764		// Set the HAB mode flag.
765		op->setIsHAB(isHAB);
766
767		return new OperationSequence(op);
768	}
769	catch (...)
770	{
771		// delete op and rethrow exception
772		if (op)
773		{
774			delete op;
775		}
776		throw;
777	}
778}
779
780//! First this method sets the default source to the source identified in
781//! the from statement. Then the statements within the from block are
782//! processed recursively by calling convertStatementList(). The resulting
783//! operation sequence is returned.
784OperationSequence * ConversionController::convertFromStatement(FromStatementASTNode * statement)
785{
786	if (m_defaultSource)
787	{
788		throw semantic_error(format_string("line %d: from statements cannot be nested", statement->getFirstLine()));
789	}
790
791	// look up source file instance
792	std::string * fromSourceName = statement->getSourceName();
793	assert(fromSourceName);
794
795	// make sure it's a valid source name
796	source_map_t::iterator sourceIt = m_sources.find(*fromSourceName);
797	if (sourceIt == m_sources.end())
798	{
799		throw semantic_error(format_string("line %d: bad source name", statement->getFirstLine()));
800	}
801
802	// set default source
803	m_defaultSource = sourceIt->second;
804	assert(m_defaultSource);
805
806	// get statements inside the from block
807	ListASTNode * fromStatements = statement->getStatements();
808	assert(fromStatements);
809
810	// produce resulting operation sequence
811	OperationSequence * result = convertStatementList(fromStatements);
812
813	// restore default source to NULL
814	m_defaultSource = NULL;
815
816	return result;
817}
818
819//! Evaluates the expression to get the new boot mode value. Then creates a
820//! BootModeOperation object and returns an OperationSequence containing it.
821//!
822//! \exception elftosb::semantic_error Thrown if a semantic problem is found with
823//!		the boot mode expression.
824OperationSequence * ConversionController::convertModeStatement(ModeStatementASTNode * statement)
825{
826	BootModeOperation * op = NULL;
827
828	try
829	{
830		op = new BootModeOperation();
831
832		// evaluate the boot mode expression
833		ExprASTNode * modeExprNode = statement->getModeExpr();
834		if (!modeExprNode)
835		{
836			throw semantic_error(format_string("line %d: mode statement has invalid boot mode expression", statement->getFirstLine()));
837		}
838		modeExprNode = modeExprNode->reduce(m_context);
839		IntConstExprASTNode * intNode = dynamic_cast<IntConstExprASTNode*>(modeExprNode);
840		if (!intNode)
841		{
842			throw semantic_error(format_string("line %d: boot mode did not evaluate to an integer", statement->getFirstLine()));
843		}
844
845		op->setBootMode(intNode->getValue());
846
847		return new OperationSequence(op);
848	}
849	catch (...)
850	{
851		if (op)
852		{
853			delete op;
854		}
855
856		// rethrow exception
857		throw;
858	}
859}
860
861//! Else branches, including else-if, are handled recursively, so there is a limit
862//! on the number of them based on the stack size.
863//!
864//! \return Returns the operation sequence for the branch of the if statement that
865//!		evaluated to true. If the statement did not have an else branch and the
866//!		condition expression evaluated to false, then NULL will be returned.
867//!
868//! \todo Handle else branches without recursion.
869OperationSequence * ConversionController::convertIfStatement(IfStatementASTNode * statement)
870{
871	// Get the if's conditional expression.
872	ExprASTNode * conditionalExpr = statement->getConditionExpr();
873	if (!conditionalExpr)
874	{
875		throw semantic_error(format_string("line %d: missing or invalid conditional expression", statement->getFirstLine()));
876	}
877
878	// Reduce the conditional to a single integer.
879	conditionalExpr = conditionalExpr->reduce(m_context);
880	IntConstExprASTNode * intNode = dynamic_cast<IntConstExprASTNode*>(conditionalExpr);
881	if (!intNode)
882	{
883		throw semantic_error(format_string("line %d: if statement conditional expression did not evaluate to an integer", statement->getFirstLine()));
884	}
885
886	// Decide which statements to further process by the conditional's boolean value.
887	if (intNode->getValue() && statement->getIfStatements())
888	{
889		return convertStatementList(statement->getIfStatements());
890	}
891	else if (statement->getElseStatements())
892	{
893		return convertStatementList(statement->getElseStatements());
894	}
895	else
896	{
897		// No else branch and the conditional was false, so there are no operations to return.
898		return NULL;
899	}
900}
901
902//! Message statements are executed immediately, by this method. They are
903//! not converted into an abstract operation. All messages are passed through
904//! substituteVariables() before being output.
905//!
906//! \param statement The message statement AST node object.
907void ConversionController::handleMessageStatement(MessageStatementASTNode * statement)
908{
909	string * message = statement->getMessage();
910	if (!message)
911	{
912		throw runtime_error("message statement had no message");
913	}
914
915	smart_ptr<string> finalMessage = substituteVariables(message);
916
917	switch (statement->getType())
918	{
919		case MessageStatementASTNode::kInfo:
920			Log::log(Logger::INFO, "%s\n", finalMessage->c_str());
921			break;
922
923		case MessageStatementASTNode::kWarning:
924			Log::log(Logger::WARNING, "warning: %s\n", finalMessage->c_str());
925			break;
926
927		case MessageStatementASTNode::kError:
928			throw runtime_error(*finalMessage);
929			break;
930	}
931}
932
933//! Performs shell-like variable substitution on the string passed into it.
934//! Both sources and constants can be substituted. Sources will be replaced
935//! with their path and constants with their integer value. The syntax allows
936//! for some simple formatting for constants.
937//!
938//! The syntax is mostly standard. A substitution begins with a dollar-sign
939//! and is followed by the source or constant name in parentheses. For instance,
940//! "$(mysource)" or "$(myconst)". The parentheses are always required.
941//!
942//! Constant names can be prefixed by a single formatting character followed
943//! by a colon. The only formatting characters currently supported are 'd' for
944//! decimal and 'x' for hex. For example, "$(x:myconst)" will be replaced with
945//! the value of the constant named "myconst" formatted as hexadecimal. The
946//! default is decimal, so the 'd' formatting character isn't really ever
947//! needed.
948//!
949//! \param message The string to perform substitution on.
950//! \return Returns a newly allocated std::string object that has all
951//!		substitutions replaced with the associated value. The caller is
952//!		responsible for freeing the string object using the delete operator.
953std::string * ConversionController::substituteVariables(const std::string * message)
954{
955	string * result = new string();
956	int i;
957	int state = 0;
958	string name;
959
960	for (i=0; i < message->size(); ++i)
961	{
962		char c = (*message)[i];
963		switch (state)
964		{
965			case 0:
966				if (c == '$')
967				{
968					state = 1;
969				}
970				else
971				{
972					(*result) += c;
973				}
974				break;
975
976			case 1:
977				if (c == '(')
978				{
979					state = 2;
980				}
981				else
982				{
983					// Wasn't a variable substitution, so revert to initial state after
984					// inserting the original characters.
985					(*result) += '$';
986					(*result) += c;
987					state = 0;
988				}
989				break;
990
991			case 2:
992				if (c == ')')
993				{
994					// Try the name as a source name first.
995					if (m_sources.find(name) != m_sources.end())
996					{
997						(*result) += m_sources[name]->getPath();
998					}
999					// Otherwise try it as a variable.
1000					else
1001					{
1002						// Select format.
1003						const char * fmt = "%d";
1004						if (name[1] == ':' && (name[0] == 'd' || name[0] == 'x'))
1005						{
1006							if (name[0] == 'x')
1007							{
1008								fmt = "0x%x";
1009							}
1010
1011							// Delete the format characters.
1012							name.erase(0, 2);
1013						}
1014
1015						// Now insert the formatted variable if it exists.
1016						if (m_context.isVariableDefined(name))
1017						{
1018							(*result) += format_string(fmt, m_context.getVariableValue(name));
1019						}
1020					}
1021
1022					// Switch back to initial state and clear name.
1023					state = 0;
1024					name.clear();
1025				}
1026				else
1027				{
1028					// Just keep building up the variable name.
1029					name += c;
1030				}
1031				break;
1032		}
1033	}
1034
1035	return result;
1036}
1037
1038//!
1039//! \param generator The generator to use.
1040BootImage * ConversionController::generateOutput(BootImageGenerator * generator)
1041{
1042	// set the generator's option context
1043	generator->setOptionContext(this);
1044
1045	// add output sections to the generator in sequence
1046	section_vector_t::iterator it = m_outputSections.begin();
1047	for (; it != m_outputSections.end(); ++it)
1048	{
1049		generator->addOutputSection(*it);
1050	}
1051
1052	// and produce the output
1053	BootImage * image = generator->generate();
1054//	Log::log("boot image = %p\n", image);
1055	return image;
1056}
1057
1058//! Takes an AST node that is one of the following subclasses and creates the corresponding
1059//! type of DataSource object from it.
1060//! - StringConstASTNode
1061//! - ExprASTNode
1062//! - SourceASTNode
1063//! - SectionASTNode
1064//! - SectionMatchListASTNode
1065//! - BlobConstASTNode
1066//! - IVTConstASTNode
1067//!
1068//! \exception elftosb::semantic_error Thrown if a semantic problem is found with
1069//!		the data node.
1070//! \exception std::runtime_error Thrown if an error occurs that shouldn't be possible
1071//!		based on the grammar.
1072DataSource * ConversionController::createSourceFromNode(ASTNode * dataNode)
1073{
1074	assert(dataNode);
1075
1076	DataSource * source = NULL;
1077	StringConstASTNode * stringNode;
1078	BlobConstASTNode * blobNode;
1079	ExprASTNode * exprNode;
1080	SourceASTNode * sourceNode;
1081	SectionASTNode * sectionNode;
1082	SectionMatchListASTNode * matchListNode;
1083    IVTConstASTNode * ivtNode;
1084
1085	if (stringNode = dynamic_cast<StringConstASTNode*>(dataNode))
1086	{
1087		// create a data source with the string contents
1088		std::string * stringData = stringNode->getString();
1089		const uint8_t * stringContents = reinterpret_cast<const uint8_t *>(stringData->c_str());
1090		source = new UnmappedDataSource(stringContents, static_cast<unsigned>(stringData->size()));
1091	}
1092	else if (blobNode = dynamic_cast<BlobConstASTNode*>(dataNode))
1093	{
1094		// create a data source with the raw binary data
1095		Blob * blob = blobNode->getBlob();
1096		source = new UnmappedDataSource(blob->getData(), blob->getLength());
1097	}
1098	else if (exprNode = dynamic_cast<ExprASTNode*>(dataNode))
1099	{
1100		// reduce the expression first
1101		exprNode = exprNode->reduce(m_context);
1102		IntConstExprASTNode * intNode = dynamic_cast<IntConstExprASTNode*>(exprNode);
1103		if (!intNode)
1104		{
1105			throw semantic_error("load pattern expression did not evaluate to an integer");
1106		}
1107
1108		SizedIntegerValue intValue(intNode->getValue(), intNode->getSize());
1109		source = new PatternSource(intValue);
1110	}
1111	else if (sourceNode = dynamic_cast<SourceASTNode*>(dataNode))
1112	{
1113		// load the entire source contents
1114		SourceFile * sourceFile = getSourceFromName(sourceNode->getSourceName(), sourceNode->getFirstLine());
1115		source = sourceFile->createDataSource();
1116	}
1117	else if (sectionNode = dynamic_cast<SectionASTNode*>(dataNode))
1118	{
1119		// load some subset of the source
1120		SourceFile * sourceFile = getSourceFromName(sectionNode->getSourceName(), sectionNode->getFirstLine());
1121		if (!sourceFile->supportsNamedSections())
1122		{
1123			throw semantic_error(format_string("line %d: source does not support sections", sectionNode->getFirstLine()));
1124		}
1125
1126		// create data source from the section name
1127		std::string * sectionName = sectionNode->getSectionName();
1128		GlobMatcher globber(*sectionName);
1129		source = sourceFile->createDataSource(globber);
1130		if (!source)
1131		{
1132			throw semantic_error(format_string("line %d: no sections match the pattern", sectionNode->getFirstLine()));
1133		}
1134	}
1135	else if (matchListNode = dynamic_cast<SectionMatchListASTNode*>(dataNode))
1136	{
1137		SourceFile * sourceFile = getSourceFromName(matchListNode->getSourceName(), matchListNode->getFirstLine());
1138		if (!sourceFile->supportsNamedSections())
1139		{
1140			throw semantic_error(format_string("line %d: source type does not support sections", matchListNode->getFirstLine()));
1141		}
1142
1143		// create string matcher
1144		ExcludesListMatcher matcher;
1145
1146		// add each pattern to the matcher
1147		ListASTNode * matchList = matchListNode->getSections();
1148		ListASTNode::iterator it = matchList->begin();
1149		for (; it != matchList->end(); ++it)
1150		{
1151			ASTNode * node = *it;
1152			sectionNode = dynamic_cast<SectionASTNode*>(node);
1153			if (!sectionNode)
1154			{
1155				throw std::runtime_error(format_string("line %d: unexpected node type in section pattern list", (*it)->getFirstLine()));
1156			}
1157			bool isInclude = sectionNode->getAction() == SectionASTNode::kInclude;
1158			matcher.addPattern(isInclude, *(sectionNode->getSectionName()));
1159		}
1160
1161		// create data source from the section match list
1162		source = sourceFile->createDataSource(matcher);
1163		if (!source)
1164		{
1165			throw semantic_error(format_string("line %d: no sections match the section pattern list", matchListNode->getFirstLine()));
1166		}
1167	}
1168    else if (ivtNode = dynamic_cast<IVTConstASTNode*>(dataNode))
1169    {
1170        source = createIVTDataSource(ivtNode);
1171    }
1172	else
1173	{
1174		throw semantic_error(format_string("line %d: unexpected load data node type", dataNode->getFirstLine()));
1175	}
1176
1177	return source;
1178}
1179
1180DataSource * ConversionController::createIVTDataSource(IVTConstASTNode * ivtNode)
1181{
1182    IVTDataSource * source = new IVTDataSource;
1183
1184    // Iterate over the assignment statements in the IVT definition.
1185    ListASTNode * fieldList = ivtNode->getFieldAssignments();
1186
1187    if (fieldList)
1188    {
1189        ListASTNode::iterator it = fieldList->begin();
1190        for (; it != fieldList->end(); ++it)
1191        {
1192            AssignmentASTNode * assignmentNode = dynamic_cast<AssignmentASTNode*>(*it);
1193            if (!assignmentNode)
1194            {
1195                throw std::runtime_error(format_string("line %d: unexpected node type in IVT definition", (*it)->getFirstLine()));
1196            }
1197
1198            // Get the IVT field name.
1199            std::string * fieldName = assignmentNode->getIdent();
1200
1201            // Reduce the field expression and get the integer result.
1202            ASTNode * valueNode = assignmentNode->getValue();
1203            ExprASTNode * valueExpr = dynamic_cast<ExprASTNode*>(valueNode);
1204            if (!valueExpr)
1205            {
1206                throw semantic_error("IVT field must have a valid expression");
1207            }
1208            IntConstExprASTNode * valueIntExpr = dynamic_cast<IntConstExprASTNode*>(valueExpr->reduce(m_context));
1209            if (!valueIntExpr)
1210            {
1211                throw semantic_error(format_string("line %d: IVT field '%s' does not evaluate to an integer", valueNode->getFirstLine(), fieldName->c_str()));
1212            }
1213            uint32_t value = static_cast<uint32_t>(valueIntExpr->getValue());
1214
1215            // Set the field in the IVT data source.
1216            if (!source->setFieldByName(*fieldName, value))
1217            {
1218                throw semantic_error(format_string("line %d: unknown IVT field '%s'", assignmentNode->getFirstLine(), fieldName->c_str()));
1219            }
1220        }
1221    }
1222
1223    return source;
1224}
1225
1226//! Takes an AST node subclass and returns an appropriate DataTarget object that contains
1227//! the same information. Supported AST node types are:
1228//! - SymbolASTNode
1229//! - NaturalLocationASTNode
1230//! - AddressRangeASTNode
1231//!
1232//! \exception elftosb::semantic_error Thrown if a semantic problem is found with
1233//!		the target node.
1234DataTarget * ConversionController::createTargetFromNode(ASTNode * targetNode)
1235{
1236	assert(targetNode);
1237
1238	DataTarget * target = NULL;
1239	SymbolASTNode * symbolNode;
1240	NaturalLocationASTNode * naturalNode;
1241	AddressRangeASTNode * addressNode;
1242
1243	if (symbolNode = dynamic_cast<SymbolASTNode*>(targetNode))
1244	{
1245		SourceFile * sourceFile = getSourceFromName(symbolNode->getSource(), symbolNode->getFirstLine());
1246		std::string * symbolName = symbolNode->getSymbolName();
1247
1248		// symbol name is optional
1249		if (symbolName)
1250		{
1251			if (!sourceFile->supportsNamedSymbols())
1252			{
1253				throw std::runtime_error(format_string("line %d: source does not support symbols", symbolNode->getFirstLine()));
1254			}
1255
1256			target = sourceFile->createDataTargetForSymbol(*symbolName);
1257			if (!target)
1258			{
1259				throw std::runtime_error(format_string("line %d: source does not have a symbol with that name", symbolNode->getFirstLine()));
1260			}
1261		}
1262		else
1263		{
1264			// no symbol name was specified so use entry point
1265			target = sourceFile->createDataTargetForEntryPoint();
1266			if (!target)
1267			{
1268				throw std::runtime_error(format_string("line %d: source does not have an entry point", symbolNode->getFirstLine()));
1269			}
1270		}
1271	}
1272	else if (naturalNode = dynamic_cast<NaturalLocationASTNode*>(targetNode))
1273	{
1274		// the target is the source's natural location
1275		target = new NaturalDataTarget();
1276	}
1277	else if (addressNode = dynamic_cast<AddressRangeASTNode*>(targetNode))
1278	{
1279		// evaluate begin address
1280		ExprASTNode * beginExpr = dynamic_cast<ExprASTNode*>(addressNode->getBegin());
1281		if (!beginExpr)
1282		{
1283			throw semantic_error("address range must always have a beginning expression");
1284		}
1285		IntConstExprASTNode * beginIntExpr = dynamic_cast<IntConstExprASTNode*>(beginExpr->reduce(m_context));
1286		if (!beginIntExpr)
1287		{
1288			throw semantic_error("address range begin did not evaluate to an integer");
1289		}
1290		uint32_t beginAddress = static_cast<uint32_t>(beginIntExpr->getValue());
1291
1292		// evaluate end address
1293		ExprASTNode * endExpr = dynamic_cast<ExprASTNode*>(addressNode->getEnd());
1294		uint32_t endAddress = 0;
1295		bool hasEndAddress = false;
1296		if (endExpr)
1297		{
1298			IntConstExprASTNode * endIntExpr = dynamic_cast<IntConstExprASTNode*>(endExpr->reduce(m_context));
1299			if (!endIntExpr)
1300			{
1301				throw semantic_error("address range end did not evaluate to an integer");
1302			}
1303			endAddress = static_cast<uint32_t>(endIntExpr->getValue());
1304			hasEndAddress = true;
1305		}
1306
1307		// create target
1308		if (hasEndAddress)
1309		{
1310			target = new ConstantDataTarget(beginAddress, endAddress);
1311		}
1312		else
1313		{
1314			target = new ConstantDataTarget(beginAddress);
1315		}
1316	}
1317	else
1318	{
1319		throw semantic_error("unexpected load target node type");
1320	}
1321
1322	return target;
1323}
1324
1325//! \param sourceName Pointer to string containing the name of the source to look up.
1326//!		May be NULL, in which case the default source is used.
1327//! \param line The line number on which the source name was located.
1328//!
1329//! \result A source file object that was previously created in the processSources()
1330//!		stage.
1331//!
1332//! \exception std::runtime_error Thrown if the source name is invalid, or if it
1333//!		was NULL and there is no default source (i.e., we're not inside a from
1334//!		statement).
1335SourceFile * ConversionController::getSourceFromName(std::string * sourceName, int line)
1336{
1337	SourceFile * sourceFile = NULL;
1338	if (sourceName)
1339	{
1340		// look up source in map
1341		source_map_t::iterator it = m_sources.find(*sourceName);
1342		if (it == m_sources.end())
1343		{
1344			source_name_vector_t::const_iterator findIt = std::find<source_name_vector_t::const_iterator, std::string>(m_failedSources.begin(), m_failedSources.end(), *sourceName);
1345			if (findIt != m_failedSources.end())
1346			{
1347				throw semantic_error(format_string("line %d: error opening source '%s'", line, sourceName->c_str()));
1348			}
1349			else
1350			{
1351				throw semantic_error(format_string("line %d: invalid source name '%s'", line, sourceName->c_str()));
1352			}
1353		}
1354		sourceFile = it->second;
1355	}
1356	else
1357	{
1358		// no name provided - use default source
1359		sourceFile = m_defaultSource;
1360		if (!sourceFile)
1361		{
1362			throw semantic_error(format_string("line %d: source required but no default source is available", line));
1363		}
1364	}
1365
1366	// open the file if it hasn't already been
1367	if (!sourceFile->isOpen())
1368	{
1369		sourceFile->open();
1370	}
1371	return sourceFile;
1372}
1373
1374//! Exercises the lexer by printing out the value of every token produced by the
1375//! lexer. It is assumed that the lexer object has already be configured to read
1376//! from some input file. The method will return when the lexer has exhausted all
1377//! tokens, or an error occurs.
1378void ConversionController::testLexer(ElftosbLexer & lexer)
1379{
1380	// test lexer
1381	while (1)
1382	{
1383		YYSTYPE value;
1384		int lexresult = lexer.yylex();
1385		if (lexresult == 0)
1386			break;
1387		lexer.getSymbolValue(&value);
1388		Log::log("%d -> int:%d, ast:%p", lexresult, value.m_int, value.m_str, value.m_ast);
1389		if (lexresult == TOK_IDENT || lexresult == TOK_SOURCE_NAME || lexresult == TOK_STRING_LITERAL)
1390		{
1391			if (value.m_str)
1392			{
1393				Log::log(", str:%s\n", value.m_str->c_str());
1394			}
1395			else
1396			{
1397				Log::log("str:NULL\n");
1398			}
1399		}
1400		else
1401		{
1402			Log::log("\n");
1403		}
1404	}
1405}
1406
1407//! Prints out the value of an integer constant expression AST node. Also prints
1408//! the name of the identifier associated with that node, as well as the integer
1409//! size.
1410void ConversionController::printIntConstExpr(const std::string & ident, IntConstExprASTNode * expr)
1411{
1412	// print constant value
1413	char sizeChar;
1414	switch (expr->getSize())
1415	{
1416		case kWordSize:
1417			sizeChar = 'w';
1418			break;
1419		case kHalfWordSize:
1420			sizeChar = 'h';
1421			break;
1422		case kByteSize:
1423			sizeChar = 'b';
1424			break;
1425	}
1426	Log::log("%s => %d:%c\n", ident.c_str(), expr->getValue(), sizeChar);
1427}
1428
1429