xref: /netbsd-src/external/bsd/elftosb/dist/common/ELFSourceFile.cpp (revision 993229b6fea628ff8b1fa09146c80b0cfb2768eb)
1*993229b6Sjkunz /*
2*993229b6Sjkunz  * File:	ELFSourceFile.cpp
3*993229b6Sjkunz  *
4*993229b6Sjkunz  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5*993229b6Sjkunz  * See included license file for license details.
6*993229b6Sjkunz  */
7*993229b6Sjkunz 
8*993229b6Sjkunz #include "ELFSourceFile.h"
9*993229b6Sjkunz #include "Logging.h"
10*993229b6Sjkunz #include "GHSSecInfo.h"
11*993229b6Sjkunz #include <ctype.h>
12*993229b6Sjkunz #include <algorithm>
13*993229b6Sjkunz #include "string.h"
14*993229b6Sjkunz 
15*993229b6Sjkunz //! The name of the toolset option.
16*993229b6Sjkunz #define kToolsetOptionName "toolset"
17*993229b6Sjkunz #define kGHSToolsetName "GHS"
18*993229b6Sjkunz #define kGCCToolsetName "GCC"
19*993229b6Sjkunz #define kGNUToolsetName "GNU"
20*993229b6Sjkunz #define kADSToolsetName "ADS"
21*993229b6Sjkunz 
22*993229b6Sjkunz //! Name of the option to control .secinfo action.
23*993229b6Sjkunz #define kSecinfoClearOptionName "secinfoClear"
24*993229b6Sjkunz #define kSecinfoDefaultName "DEFAULT"
25*993229b6Sjkunz #define kSecinfoIgnoreName "IGNORE"
26*993229b6Sjkunz #define kSecinfoROMName "ROM"
27*993229b6Sjkunz #define kSecinfoCName "C"
28*993229b6Sjkunz 
29*993229b6Sjkunz using namespace elftosb;
30*993229b6Sjkunz 
ELFSourceFile(const std::string & path)31*993229b6Sjkunz ELFSourceFile::ELFSourceFile(const std::string & path)
32*993229b6Sjkunz :	SourceFile(path),
33*993229b6Sjkunz 	m_toolset(kUnknownToolset),
34*993229b6Sjkunz 	m_secinfoOption(kSecinfoDefault)
35*993229b6Sjkunz {
36*993229b6Sjkunz }
37*993229b6Sjkunz 
~ELFSourceFile()38*993229b6Sjkunz ELFSourceFile::~ELFSourceFile()
39*993229b6Sjkunz {
40*993229b6Sjkunz }
41*993229b6Sjkunz 
isELFFile(std::istream & stream)42*993229b6Sjkunz bool ELFSourceFile::isELFFile(std::istream & stream)
43*993229b6Sjkunz {
44*993229b6Sjkunz 	try
45*993229b6Sjkunz 	{
46*993229b6Sjkunz 		StELFFile elf(stream);
47*993229b6Sjkunz 		return true;
48*993229b6Sjkunz 	}
49*993229b6Sjkunz 	catch (...)
50*993229b6Sjkunz 	{
51*993229b6Sjkunz 		return false;
52*993229b6Sjkunz 	}
53*993229b6Sjkunz }
54*993229b6Sjkunz 
open()55*993229b6Sjkunz void ELFSourceFile::open()
56*993229b6Sjkunz {
57*993229b6Sjkunz 	// Read toolset option
58*993229b6Sjkunz 	m_toolset = readToolsetOption();
59*993229b6Sjkunz 
60*993229b6Sjkunz 	// Read option and select default value
61*993229b6Sjkunz 	m_secinfoOption = readSecinfoClearOption();
62*993229b6Sjkunz 	if (m_secinfoOption == kSecinfoDefault)
63*993229b6Sjkunz 	{
64*993229b6Sjkunz 		m_secinfoOption = kSecinfoCStartupClear;
65*993229b6Sjkunz 	}
66*993229b6Sjkunz 
67*993229b6Sjkunz 	// Open the stream
68*993229b6Sjkunz 	SourceFile::open();
69*993229b6Sjkunz 
70*993229b6Sjkunz 	m_file = new StELFFile(*m_stream);
71*993229b6Sjkunz //	m_file->dumpSections();
72*993229b6Sjkunz 
73*993229b6Sjkunz 	// Set toolset in elf file object
74*993229b6Sjkunz 	switch (m_toolset)
75*993229b6Sjkunz 	{
76*993229b6Sjkunz         // default toolset is GHS
77*993229b6Sjkunz 		case kGHSToolset:
78*993229b6Sjkunz         case kUnknownToolset:
79*993229b6Sjkunz 			m_file->setELFVariant(eGHSVariant);
80*993229b6Sjkunz 			break;
81*993229b6Sjkunz 		case kGCCToolset:
82*993229b6Sjkunz 			m_file->setELFVariant(eGCCVariant);
83*993229b6Sjkunz 			break;
84*993229b6Sjkunz 		case kADSToolset:
85*993229b6Sjkunz 			m_file->setELFVariant(eARMVariant);
86*993229b6Sjkunz 			break;
87*993229b6Sjkunz 	}
88*993229b6Sjkunz }
89*993229b6Sjkunz 
close()90*993229b6Sjkunz void ELFSourceFile::close()
91*993229b6Sjkunz {
92*993229b6Sjkunz 	SourceFile::close();
93*993229b6Sjkunz 
94*993229b6Sjkunz 	m_file.safe_delete();
95*993229b6Sjkunz }
96*993229b6Sjkunz 
readToolsetOption()97*993229b6Sjkunz elf_toolset_t ELFSourceFile::readToolsetOption()
98*993229b6Sjkunz {
99*993229b6Sjkunz 	do {
100*993229b6Sjkunz 		const OptionContext * options = getOptions();
101*993229b6Sjkunz 		if (!options || !options->hasOption(kToolsetOptionName))
102*993229b6Sjkunz 		{
103*993229b6Sjkunz 			break;
104*993229b6Sjkunz 		}
105*993229b6Sjkunz 
106*993229b6Sjkunz 		const Value * value = options->getOption(kToolsetOptionName);
107*993229b6Sjkunz 		const StringValue * stringValue = dynamic_cast<const StringValue*>(value);
108*993229b6Sjkunz 		if (!stringValue)
109*993229b6Sjkunz 		{
110*993229b6Sjkunz 			// Not a string value, warn the user.
111*993229b6Sjkunz 			Log::log(Logger::WARNING, "invalid type for 'toolset' option\n");
112*993229b6Sjkunz 			break;
113*993229b6Sjkunz 		}
114*993229b6Sjkunz 
115*993229b6Sjkunz 		std::string toolsetName = *stringValue;
116*993229b6Sjkunz 
117*993229b6Sjkunz 		// convert option value to uppercase
118*993229b6Sjkunz 		std::transform<std::string::const_iterator, std::string::iterator, int (*)(int)>(toolsetName.begin(), toolsetName.end(), toolsetName.begin(), toupper);
119*993229b6Sjkunz 
120*993229b6Sjkunz 		if (toolsetName == kGHSToolsetName)
121*993229b6Sjkunz 		{
122*993229b6Sjkunz 			return kGHSToolset;
123*993229b6Sjkunz 		}
124*993229b6Sjkunz 		else if (toolsetName == kGCCToolsetName || toolsetName == kGNUToolsetName)
125*993229b6Sjkunz 		{
126*993229b6Sjkunz 			return kGCCToolset;
127*993229b6Sjkunz 		}
128*993229b6Sjkunz 		else if (toolsetName == kADSToolsetName)
129*993229b6Sjkunz 		{
130*993229b6Sjkunz 			return kADSToolset;
131*993229b6Sjkunz 		}
132*993229b6Sjkunz 
133*993229b6Sjkunz 		// Unrecognized option value, log a warning.
134*993229b6Sjkunz 		Log::log(Logger::WARNING, "unrecognized value for 'toolset' option\n");
135*993229b6Sjkunz 	} while (0);
136*993229b6Sjkunz 
137*993229b6Sjkunz 	return kUnknownToolset;
138*993229b6Sjkunz }
139*993229b6Sjkunz 
140*993229b6Sjkunz //! It is up to the caller to convert from kSecinfoDefault to the actual default
141*993229b6Sjkunz //! value.
readSecinfoClearOption()142*993229b6Sjkunz secinfo_clear_t ELFSourceFile::readSecinfoClearOption()
143*993229b6Sjkunz {
144*993229b6Sjkunz 	do {
145*993229b6Sjkunz 		const OptionContext * options = getOptions();
146*993229b6Sjkunz 		if (!options || !options->hasOption(kSecinfoClearOptionName))
147*993229b6Sjkunz 		{
148*993229b6Sjkunz 			break;
149*993229b6Sjkunz 		}
150*993229b6Sjkunz 
151*993229b6Sjkunz 		const Value * value = options->getOption(kSecinfoClearOptionName);
152*993229b6Sjkunz 		const StringValue * stringValue = dynamic_cast<const StringValue*>(value);
153*993229b6Sjkunz 		if (!stringValue)
154*993229b6Sjkunz 		{
155*993229b6Sjkunz 			// Not a string value, warn the user.
156*993229b6Sjkunz 			Log::log(Logger::WARNING, "invalid type for 'secinfoClear' option\n");
157*993229b6Sjkunz 			break;
158*993229b6Sjkunz 		}
159*993229b6Sjkunz 
160*993229b6Sjkunz 		std::string secinfoOption = *stringValue;
161*993229b6Sjkunz 
162*993229b6Sjkunz 		// convert option value to uppercase
163*993229b6Sjkunz 		std::transform<std::string::const_iterator, std::string::iterator, int (*)(int)>(secinfoOption.begin(), secinfoOption.end(), secinfoOption.begin(), toupper);
164*993229b6Sjkunz 
165*993229b6Sjkunz 		if (secinfoOption == kSecinfoDefaultName)
166*993229b6Sjkunz 		{
167*993229b6Sjkunz 			return kSecinfoDefault;
168*993229b6Sjkunz 		}
169*993229b6Sjkunz 		else if (secinfoOption == kSecinfoIgnoreName)
170*993229b6Sjkunz 		{
171*993229b6Sjkunz 			return kSecinfoIgnore;
172*993229b6Sjkunz 		}
173*993229b6Sjkunz 		else if (secinfoOption == kSecinfoROMName)
174*993229b6Sjkunz 		{
175*993229b6Sjkunz 			return kSecinfoROMClear;
176*993229b6Sjkunz 		}
177*993229b6Sjkunz 		else if (secinfoOption == kSecinfoCName)
178*993229b6Sjkunz 		{
179*993229b6Sjkunz 			return kSecinfoCStartupClear;
180*993229b6Sjkunz 		}
181*993229b6Sjkunz 
182*993229b6Sjkunz 		// Unrecognized option value, log a warning.
183*993229b6Sjkunz 		Log::log(Logger::WARNING, "unrecognized value for 'secinfoClear' option\n");
184*993229b6Sjkunz 	} while (0);
185*993229b6Sjkunz 
186*993229b6Sjkunz 	return kSecinfoDefault;
187*993229b6Sjkunz }
188*993229b6Sjkunz 
189*993229b6Sjkunz //! To create a data source for all sections of the ELF file, a WildcardMatcher
190*993229b6Sjkunz //! is instantiated and passed to createDataSource(StringMatcher&).
createDataSource()191*993229b6Sjkunz DataSource * ELFSourceFile::createDataSource()
192*993229b6Sjkunz {
193*993229b6Sjkunz 	WildcardMatcher matcher;
194*993229b6Sjkunz 	return createDataSource(matcher);
195*993229b6Sjkunz }
196*993229b6Sjkunz 
createDataSource(StringMatcher & matcher)197*993229b6Sjkunz DataSource * ELFSourceFile::createDataSource(StringMatcher & matcher)
198*993229b6Sjkunz {
199*993229b6Sjkunz 	assert(m_file);
200*993229b6Sjkunz 	ELFDataSource * source = new ELFDataSource(m_file);
201*993229b6Sjkunz 	source->setSecinfoOption(m_secinfoOption);
202*993229b6Sjkunz 
203*993229b6Sjkunz 	Log::log(Logger::DEBUG2, "filtering sections of file: %s\n", getPath().c_str());
204*993229b6Sjkunz 
205*993229b6Sjkunz 	// We start at section 1 to skip the null section that is always first.
206*993229b6Sjkunz 	unsigned index = 1;
207*993229b6Sjkunz 	for (; index < m_file->getSectionCount(); ++index)
208*993229b6Sjkunz 	{
209*993229b6Sjkunz 		const Elf32_Shdr & header = m_file->getSectionAtIndex(index);
210*993229b6Sjkunz 		std::string name = m_file->getSectionNameAtIndex(header.sh_name);
211*993229b6Sjkunz 
212*993229b6Sjkunz 		// Ignore most section types
213*993229b6Sjkunz 		if (!(header.sh_type == SHT_PROGBITS || header.sh_type == SHT_NOBITS))
214*993229b6Sjkunz 		{
215*993229b6Sjkunz 			continue;
216*993229b6Sjkunz 		}
217*993229b6Sjkunz 
218*993229b6Sjkunz 		// Ignore sections that don't have the allocate flag set.
219*993229b6Sjkunz 		if ((header.sh_flags & SHF_ALLOC) == 0)
220*993229b6Sjkunz 		{
221*993229b6Sjkunz 			continue;
222*993229b6Sjkunz 		}
223*993229b6Sjkunz 
224*993229b6Sjkunz 		if (matcher.match(name))
225*993229b6Sjkunz 		{
226*993229b6Sjkunz 			Log::log(Logger::DEBUG2, "creating segment for section %s\n", name.c_str());
227*993229b6Sjkunz 			source->addSection(index);
228*993229b6Sjkunz 		}
229*993229b6Sjkunz 		else
230*993229b6Sjkunz 		{
231*993229b6Sjkunz 			Log::log(Logger::DEBUG2, "section %s did not match\n", name.c_str());
232*993229b6Sjkunz 		}
233*993229b6Sjkunz 	}
234*993229b6Sjkunz 
235*993229b6Sjkunz 	return source;
236*993229b6Sjkunz }
237*993229b6Sjkunz 
238*993229b6Sjkunz //! It is assumed that all ELF files have an entry point.
239*993229b6Sjkunz //!
hasEntryPoint()240*993229b6Sjkunz bool ELFSourceFile::hasEntryPoint()
241*993229b6Sjkunz {
242*993229b6Sjkunz 	return true;
243*993229b6Sjkunz }
244*993229b6Sjkunz 
245*993229b6Sjkunz //! The StELFFile::getTypeOfSymbolAtIndex() method uses different methods of determining
246*993229b6Sjkunz //! ARM/Thumb mode depending on the toolset.
getEntryPointAddress()247*993229b6Sjkunz uint32_t ELFSourceFile::getEntryPointAddress()
248*993229b6Sjkunz {
249*993229b6Sjkunz 	uint32_t entryPoint = 0;
250*993229b6Sjkunz 
251*993229b6Sjkunz 	// get entry point address
252*993229b6Sjkunz 	const Elf32_Ehdr & header = m_file->getFileHeader();
253*993229b6Sjkunz 
254*993229b6Sjkunz 	// find symbol corresponding to entry point and determine if
255*993229b6Sjkunz 	// it is arm or thumb mode
256*993229b6Sjkunz 	unsigned symbolIndex = m_file->getIndexOfSymbolAtAddress(header.e_entry);
257*993229b6Sjkunz 	if (symbolIndex != 0)
258*993229b6Sjkunz 	{
259*993229b6Sjkunz 		ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(symbolIndex);
260*993229b6Sjkunz 		bool entryPointIsThumb = (symbolType == eThumbSymbol);
261*993229b6Sjkunz 		const Elf32_Sym & symbol = m_file->getSymbolAtIndex(symbolIndex);
262*993229b6Sjkunz 		std::string symbolName = m_file->getSymbolName(symbol);
263*993229b6Sjkunz 
264*993229b6Sjkunz 		Log::log(Logger::DEBUG2, "Entry point is %s@0x%08x (%s)\n", symbolName.c_str(), symbol.st_value, entryPointIsThumb ? "Thumb" : "ARM");
265*993229b6Sjkunz 
266*993229b6Sjkunz 		// set entry point, setting the low bit if it is thumb mode
267*993229b6Sjkunz 		entryPoint = header.e_entry + (entryPointIsThumb ? 1 : 0);
268*993229b6Sjkunz 	}
269*993229b6Sjkunz 	else
270*993229b6Sjkunz 	{
271*993229b6Sjkunz 		entryPoint = header.e_entry;
272*993229b6Sjkunz 	}
273*993229b6Sjkunz 
274*993229b6Sjkunz 	return entryPoint;
275*993229b6Sjkunz }
276*993229b6Sjkunz 
277*993229b6Sjkunz //! \return A DataTarget that describes the named section.
278*993229b6Sjkunz //! \retval NULL There was no section with the requested name.
createDataTargetForSection(const std::string & section)279*993229b6Sjkunz DataTarget * ELFSourceFile::createDataTargetForSection(const std::string & section)
280*993229b6Sjkunz {
281*993229b6Sjkunz 	assert(m_file);
282*993229b6Sjkunz 	unsigned index = m_file->getIndexOfSectionWithName(section);
283*993229b6Sjkunz 	if (index == SHN_UNDEF)
284*993229b6Sjkunz 	{
285*993229b6Sjkunz 		return NULL;
286*993229b6Sjkunz 	}
287*993229b6Sjkunz 
288*993229b6Sjkunz 	const Elf32_Shdr & sectionHeader = m_file->getSectionAtIndex(index);
289*993229b6Sjkunz 	uint32_t beginAddress = sectionHeader.sh_addr;
290*993229b6Sjkunz 	uint32_t endAddress = beginAddress + sectionHeader.sh_size;
291*993229b6Sjkunz 	ConstantDataTarget * target = new ConstantDataTarget(beginAddress, endAddress);
292*993229b6Sjkunz 	return target;
293*993229b6Sjkunz }
294*993229b6Sjkunz 
295*993229b6Sjkunz //! \return A DataTarget instance pointing at the requested symbol.
296*993229b6Sjkunz //! \retval NULL No symbol matching the requested name was found.
createDataTargetForSymbol(const std::string & symbol)297*993229b6Sjkunz DataTarget * ELFSourceFile::createDataTargetForSymbol(const std::string & symbol)
298*993229b6Sjkunz {
299*993229b6Sjkunz 	assert(m_file);
300*993229b6Sjkunz 	unsigned symbolCount = m_file->getSymbolCount();
301*993229b6Sjkunz 	unsigned i;
302*993229b6Sjkunz 
303*993229b6Sjkunz 	for (i=0; i < symbolCount; ++i)
304*993229b6Sjkunz 	{
305*993229b6Sjkunz 		const Elf32_Sym & symbolHeader = m_file->getSymbolAtIndex(i);
306*993229b6Sjkunz 		std::string symbolName = m_file->getSymbolName(symbolHeader);
307*993229b6Sjkunz 		if (symbolName == symbol)
308*993229b6Sjkunz 		{
309*993229b6Sjkunz             ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(i);
310*993229b6Sjkunz             bool symbolIsThumb = (symbolType == eThumbSymbol);
311*993229b6Sjkunz 
312*993229b6Sjkunz 			uint32_t beginAddress = symbolHeader.st_value + (symbolIsThumb ? 1 : 0);
313*993229b6Sjkunz 			uint32_t endAddress = beginAddress + symbolHeader.st_size;
314*993229b6Sjkunz 			ConstantDataTarget * target = new ConstantDataTarget(beginAddress, endAddress);
315*993229b6Sjkunz 			return target;
316*993229b6Sjkunz 		}
317*993229b6Sjkunz 	}
318*993229b6Sjkunz 
319*993229b6Sjkunz 	// didn't find a matching symbol
320*993229b6Sjkunz 	return NULL;
321*993229b6Sjkunz }
322*993229b6Sjkunz 
hasSymbol(const std::string & name)323*993229b6Sjkunz bool ELFSourceFile::hasSymbol(const std::string & name)
324*993229b6Sjkunz {
325*993229b6Sjkunz 	Elf32_Sym symbol;
326*993229b6Sjkunz 	return lookupSymbol(name, symbol);
327*993229b6Sjkunz }
328*993229b6Sjkunz 
getSymbolValue(const std::string & name)329*993229b6Sjkunz uint32_t ELFSourceFile::getSymbolValue(const std::string & name)
330*993229b6Sjkunz {
331*993229b6Sjkunz 	unsigned symbolCount = m_file->getSymbolCount();
332*993229b6Sjkunz 	unsigned i;
333*993229b6Sjkunz 
334*993229b6Sjkunz 	for (i=0; i < symbolCount; ++i)
335*993229b6Sjkunz 	{
336*993229b6Sjkunz 		const Elf32_Sym & symbolHeader = m_file->getSymbolAtIndex(i);
337*993229b6Sjkunz 		std::string symbolName = m_file->getSymbolName(symbolHeader);
338*993229b6Sjkunz 		if (symbolName == name)
339*993229b6Sjkunz 		{
340*993229b6Sjkunz             // If the symbol is a function, then we check to see if it is Thumb code and set bit 0 if so.
341*993229b6Sjkunz             if (ELF32_ST_TYPE(symbolHeader.st_info) == STT_FUNC)
342*993229b6Sjkunz             {
343*993229b6Sjkunz                 ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(i);
344*993229b6Sjkunz                 bool symbolIsThumb = (symbolType == eThumbSymbol);
345*993229b6Sjkunz                 return symbolHeader.st_value + (symbolIsThumb ? 1 : 0);
346*993229b6Sjkunz             }
347*993229b6Sjkunz             else
348*993229b6Sjkunz             {
349*993229b6Sjkunz 			    return symbolHeader.st_value;
350*993229b6Sjkunz             }
351*993229b6Sjkunz 		}
352*993229b6Sjkunz 	}
353*993229b6Sjkunz 
354*993229b6Sjkunz     // Couldn't find the symbol, so return 0.
355*993229b6Sjkunz 	return 0;
356*993229b6Sjkunz }
357*993229b6Sjkunz 
getSymbolSize(const std::string & name)358*993229b6Sjkunz unsigned ELFSourceFile::getSymbolSize(const std::string & name)
359*993229b6Sjkunz {
360*993229b6Sjkunz 	Elf32_Sym symbol;
361*993229b6Sjkunz 	if (!lookupSymbol(name, symbol))
362*993229b6Sjkunz 	{
363*993229b6Sjkunz 		return 0;
364*993229b6Sjkunz 	}
365*993229b6Sjkunz 
366*993229b6Sjkunz 	return symbol.st_size;
367*993229b6Sjkunz }
368*993229b6Sjkunz 
369*993229b6Sjkunz //! \param name The name of the symbol on which info is wanted.
370*993229b6Sjkunz //! \param[out] info Upon succssful return this is filled in with the symbol's information.
371*993229b6Sjkunz //!
372*993229b6Sjkunz //! \retval true The symbol was found and \a info is valid.
373*993229b6Sjkunz //! \retval false No symbol with \a name was found in the file.
lookupSymbol(const std::string & name,Elf32_Sym & info)374*993229b6Sjkunz bool ELFSourceFile::lookupSymbol(const std::string & name, Elf32_Sym & info)
375*993229b6Sjkunz {
376*993229b6Sjkunz 	assert(m_file);
377*993229b6Sjkunz 	unsigned symbolCount = m_file->getSymbolCount();
378*993229b6Sjkunz 	unsigned i;
379*993229b6Sjkunz 
380*993229b6Sjkunz 	for (i=0; i < symbolCount; ++i)
381*993229b6Sjkunz 	{
382*993229b6Sjkunz 		const Elf32_Sym & symbol = m_file->getSymbolAtIndex(i);
383*993229b6Sjkunz 		std::string thisSymbolName = m_file->getSymbolName(symbol);
384*993229b6Sjkunz 
385*993229b6Sjkunz 		// Is this the symbol we're looking for?
386*993229b6Sjkunz 		if (thisSymbolName == name)
387*993229b6Sjkunz 		{
388*993229b6Sjkunz 			info = symbol;
389*993229b6Sjkunz 			return true;
390*993229b6Sjkunz 		}
391*993229b6Sjkunz 	}
392*993229b6Sjkunz 
393*993229b6Sjkunz 	// Didn't file the symbol.
394*993229b6Sjkunz 	return false;
395*993229b6Sjkunz }
396*993229b6Sjkunz 
~ELFDataSource()397*993229b6Sjkunz ELFSourceFile::ELFDataSource::~ELFDataSource()
398*993229b6Sjkunz {
399*993229b6Sjkunz 	segment_vector_t::iterator it = m_segments.begin();
400*993229b6Sjkunz 	for (; it != m_segments.end(); ++it)
401*993229b6Sjkunz 	{
402*993229b6Sjkunz 		delete *it;
403*993229b6Sjkunz 	}
404*993229b6Sjkunz }
405*993229b6Sjkunz 
406*993229b6Sjkunz //! Not all sections will actually result in a new segment being created. Only
407*993229b6Sjkunz //! those sections whose type is #SHT_PROGBITS or #SHT_NOBITS will create
408*993229b6Sjkunz //! a new segment. Also, only sections whose size is non-zero will actually
409*993229b6Sjkunz //! create a segment.
410*993229b6Sjkunz //!
411*993229b6Sjkunz //! In addition to this, ELF files that have been marked as being created by
412*993229b6Sjkunz //! the Green Hills Software toolset have an extra step. #SHT_NOBITS sections
413*993229b6Sjkunz //! are looked up in the .secinfo section to determine if they really
414*993229b6Sjkunz //! should be filled. If not in the .secinfo table, no segment will be
415*993229b6Sjkunz //! created for the section.
addSection(unsigned sectionIndex)416*993229b6Sjkunz void ELFSourceFile::ELFDataSource::addSection(unsigned sectionIndex)
417*993229b6Sjkunz {
418*993229b6Sjkunz 	// get section info
419*993229b6Sjkunz 	const Elf32_Shdr & section = m_elf->getSectionAtIndex(sectionIndex);
420*993229b6Sjkunz 	if (section.sh_size == 0)
421*993229b6Sjkunz 	{
422*993229b6Sjkunz 		// empty section, so ignore it
423*993229b6Sjkunz 		return;
424*993229b6Sjkunz 	}
425*993229b6Sjkunz 
426*993229b6Sjkunz 	// create the right segment subclass based on the section type
427*993229b6Sjkunz 	DataSource::Segment * segment = NULL;
428*993229b6Sjkunz 	if (section.sh_type == SHT_PROGBITS)
429*993229b6Sjkunz 	{
430*993229b6Sjkunz 		segment = new ProgBitsSegment(*this, m_elf, sectionIndex);
431*993229b6Sjkunz 	}
432*993229b6Sjkunz 	else if (section.sh_type == SHT_NOBITS)
433*993229b6Sjkunz 	{
434*993229b6Sjkunz 		// Always add NOBITS sections by default.
435*993229b6Sjkunz 		bool addNobits = true;
436*993229b6Sjkunz 
437*993229b6Sjkunz 		// For GHS ELF files, we use the secinfoClear option to figure out what to do.
438*993229b6Sjkunz 		// If set to ignore, treat like a normal ELF file and always add. If set to
439*993229b6Sjkunz 		// ROM, then only clear if the section is listed in .secinfo. Otherwise if set
440*993229b6Sjkunz 		// to C startup, then let the C startup do all clearing.
441*993229b6Sjkunz 		if (m_elf->ELFVariant() == eGHSVariant)
442*993229b6Sjkunz 		{
443*993229b6Sjkunz 			GHSSecInfo secinfo(m_elf);
444*993229b6Sjkunz 
445*993229b6Sjkunz 			// If there isn't a .secinfo section present then use the normal ELF rules
446*993229b6Sjkunz 			// and always add NOBITS sections.
447*993229b6Sjkunz 			if (secinfo.hasSecinfo() && m_secinfoOption != kSecinfoIgnore)
448*993229b6Sjkunz 			{
449*993229b6Sjkunz 				switch (m_secinfoOption)
450*993229b6Sjkunz 				{
451*993229b6Sjkunz 					case kSecinfoROMClear:
452*993229b6Sjkunz 						addNobits = secinfo.isSectionFilled(section);
453*993229b6Sjkunz 						break;
454*993229b6Sjkunz 
455*993229b6Sjkunz 					case kSecinfoCStartupClear:
456*993229b6Sjkunz 						addNobits = false;
457*993229b6Sjkunz 						break;
458*993229b6Sjkunz 				}
459*993229b6Sjkunz 			}
460*993229b6Sjkunz 		}
461*993229b6Sjkunz 
462*993229b6Sjkunz 		if (addNobits)
463*993229b6Sjkunz 		{
464*993229b6Sjkunz 			segment = new NoBitsSegment(*this, m_elf, sectionIndex);
465*993229b6Sjkunz 		}
466*993229b6Sjkunz 		else
467*993229b6Sjkunz 		{
468*993229b6Sjkunz 			std::string name = m_elf->getSectionNameAtIndex(section.sh_name);
469*993229b6Sjkunz 			Log::log(Logger::DEBUG2, "..section %s is not filled\n", name.c_str());
470*993229b6Sjkunz 		}
471*993229b6Sjkunz 	}
472*993229b6Sjkunz 
473*993229b6Sjkunz 	// add segment if one was created
474*993229b6Sjkunz 	if (segment)
475*993229b6Sjkunz 	{
476*993229b6Sjkunz 		m_segments.push_back(segment);
477*993229b6Sjkunz 	}
478*993229b6Sjkunz }
479*993229b6Sjkunz 
ProgBitsSegment(ELFDataSource & source,StELFFile * elf,unsigned index)480*993229b6Sjkunz ELFSourceFile::ELFDataSource::ProgBitsSegment::ProgBitsSegment(ELFDataSource & source, StELFFile * elf, unsigned index)
481*993229b6Sjkunz :	DataSource::Segment(source), m_elf(elf), m_sectionIndex(index)
482*993229b6Sjkunz {
483*993229b6Sjkunz }
484*993229b6Sjkunz 
getData(unsigned offset,unsigned maxBytes,uint8_t * buffer)485*993229b6Sjkunz unsigned ELFSourceFile::ELFDataSource::ProgBitsSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
486*993229b6Sjkunz {
487*993229b6Sjkunz 	const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
488*993229b6Sjkunz 	uint8_t * data = m_elf->getSectionDataAtIndex(m_sectionIndex);
489*993229b6Sjkunz 
490*993229b6Sjkunz 	assert(offset < section.sh_size);
491*993229b6Sjkunz 
492*993229b6Sjkunz 	unsigned copyBytes = std::min<unsigned>(section.sh_size - offset, maxBytes);
493*993229b6Sjkunz 	if (copyBytes)
494*993229b6Sjkunz 	{
495*993229b6Sjkunz 		memcpy(buffer, &data[offset], copyBytes);
496*993229b6Sjkunz 	}
497*993229b6Sjkunz 
498*993229b6Sjkunz 	return copyBytes;
499*993229b6Sjkunz }
500*993229b6Sjkunz 
getLength()501*993229b6Sjkunz unsigned ELFSourceFile::ELFDataSource::ProgBitsSegment::getLength()
502*993229b6Sjkunz {
503*993229b6Sjkunz 	const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
504*993229b6Sjkunz 	return section.sh_size;
505*993229b6Sjkunz }
506*993229b6Sjkunz 
getBaseAddress()507*993229b6Sjkunz uint32_t ELFSourceFile::ELFDataSource::ProgBitsSegment::getBaseAddress()
508*993229b6Sjkunz {
509*993229b6Sjkunz 	const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
510*993229b6Sjkunz 	return section.sh_addr;
511*993229b6Sjkunz }
512*993229b6Sjkunz 
NoBitsSegment(ELFDataSource & source,StELFFile * elf,unsigned index)513*993229b6Sjkunz ELFSourceFile::ELFDataSource::NoBitsSegment::NoBitsSegment(ELFDataSource & source, StELFFile * elf, unsigned index)
514*993229b6Sjkunz :	DataSource::PatternSegment(source), m_elf(elf), m_sectionIndex(index)
515*993229b6Sjkunz {
516*993229b6Sjkunz }
517*993229b6Sjkunz 
getLength()518*993229b6Sjkunz unsigned ELFSourceFile::ELFDataSource::NoBitsSegment::getLength()
519*993229b6Sjkunz {
520*993229b6Sjkunz 	const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
521*993229b6Sjkunz 	return section.sh_size;
522*993229b6Sjkunz }
523*993229b6Sjkunz 
getBaseAddress()524*993229b6Sjkunz uint32_t ELFSourceFile::ELFDataSource::NoBitsSegment::getBaseAddress()
525*993229b6Sjkunz {
526*993229b6Sjkunz 	const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
527*993229b6Sjkunz 	return section.sh_addr;
528*993229b6Sjkunz }
529*993229b6Sjkunz 
530