source: CLRX/CLRadeonExtender/trunk/amdbin/ElfBinaries.cpp @ 2573

Last change on this file since 2573 was 2573, checked in by matszpk, 4 years ago

CLRadeonExtender: ElfBinGen?: Fixed STRSZ in '.dynamic' section.
ROCmBinGen: Add empty '.AMDGPU.config' section.

File size: 49.4 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2016 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#include <cstdlib>
22#include <cstring>
23#include <cstdint>
24#include <climits>
25#include <utility>
26#include <string>
27#include <cassert>
28#include <CLRX/amdbin/Elf.h>
29#include <CLRX/utils/Utilities.h>
30#include <CLRX/utils/MemAccess.h>
31#include <CLRX/amdbin/AmdBinaries.h>
32
33static const uint32_t elfMagicValue = 0x464c457fU;
34
35/* INFO: in this file is used ULEV function for conversion
36 * from LittleEndian and unaligned access to other memory access policy and endianness
37 * Please use this function whenever you want to get or set word in ELF binary,
38 * because ELF binaries can be unaligned in memory (as inner binaries).
39 */
40
41using namespace CLRX;
42
43/* determine unfinished strings region in string table for checking further consistency */
44static size_t unfinishedRegionOfStringTable(const cxbyte* table, size_t size)
45{
46    if (size == 0) // if zero
47        return 0;
48    size_t k;
49    for (k = size-1; k>0 && table[k]!=0; k--);
50   
51    return (table[k]==0)?k+1:k;
52}
53
54/* elf32 types */
55
56const cxbyte CLRX::Elf32Types::ELFCLASS = ELFCLASS32;
57const uint32_t CLRX::Elf32Types::bitness = 32;
58const char* CLRX::Elf32Types::bitName = "32";
59
60/* elf64 types */
61
62const cxbyte CLRX::Elf64Types::ELFCLASS = ELFCLASS64;
63const cxuint CLRX::Elf64Types::bitness = 64;
64const char* CLRX::Elf64Types::bitName = "64";
65
66/* ElfBinaryTemplate */
67
68template<typename Types>
69ElfBinaryTemplate<Types>::ElfBinaryTemplate() : binaryCodeSize(0), binaryCode(nullptr),
70        sectionStringTable(nullptr), symbolStringTable(nullptr),
71        symbolTable(nullptr), dynSymStringTable(nullptr), dynSymTable(nullptr),
72        noteTable(nullptr), symbolsNum(0), dynSymbolsNum(0),
73        noteTableSize(0), dynamicsNum(0), symbolEntSize(0), dynSymEntSize(0),
74        dynamicEntSize(0)
75{ }
76
77template<typename Types>
78ElfBinaryTemplate<Types>::~ElfBinaryTemplate()
79{ }
80
81template<typename Types>
82ElfBinaryTemplate<Types>::ElfBinaryTemplate(size_t _binaryCodeSize, cxbyte* _binaryCode,
83             Flags _creationFlags) : creationFlags(_creationFlags),
84        binaryCodeSize(_binaryCodeSize), binaryCode(_binaryCode),
85        sectionStringTable(nullptr), symbolStringTable(nullptr),
86        symbolTable(nullptr), dynSymStringTable(nullptr), dynSymTable(nullptr),
87        noteTable(nullptr), symbolsNum(0), dynSymbolsNum(0),
88        noteTableSize(0), dynamicsNum(0), symbolEntSize(0), dynSymEntSize(0),
89        dynamicEntSize(0)     
90{
91    if (binaryCodeSize < sizeof(typename Types::Ehdr))
92        throw Exception("Binary is too small!!!");
93   
94    const typename Types::Ehdr* ehdr =
95            reinterpret_cast<const typename Types::Ehdr*>(binaryCode);
96   
97    if (ULEV(*reinterpret_cast<const uint32_t*>(binaryCode)) != elfMagicValue)
98        throw Exception("This is not ELF binary");
99    if (ehdr->e_ident[EI_CLASS] != Types::ELFCLASS)
100        throw Exception(std::string("This is not ")+Types::bitName+"bit ELF binary");
101    if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
102        throw Exception("Other than little-endian binaries are not supported!");
103   
104    if ((ULEV(ehdr->e_phoff) == 0 && ULEV(ehdr->e_phnum) != 0))
105        throw Exception("Elf invalid phoff and phnum combination");
106    if (ULEV(ehdr->e_phoff) != 0)
107    {   /* reading and checking program headers */
108        if (ULEV(ehdr->e_phoff) > binaryCodeSize)
109            throw Exception("ProgramHeaders offset out of range!");
110        if (usumGt(ULEV(ehdr->e_phoff),
111                   ((typename Types::Word)ULEV(ehdr->e_phentsize))*ULEV(ehdr->e_phnum),
112                   binaryCodeSize))
113            throw Exception("ProgramHeaders offset+size out of range!");
114       
115        cxuint phnum = ULEV(ehdr->e_phnum);
116        // checking program header segment offset ranges
117        for (cxuint i = 0; i < phnum; i++)
118        {
119            const typename Types::Phdr& phdr = getProgramHeader(i);
120            if (ULEV(phdr.p_offset) > binaryCodeSize)
121                throw Exception("Segment offset out of range!");
122            if (usumGt(ULEV(phdr.p_offset), ULEV(phdr.p_filesz), binaryCodeSize))
123                throw Exception("Segment offset+size out of range!");
124        }
125    }
126   
127    if ((ULEV(ehdr->e_shoff) == 0 && ULEV(ehdr->e_shnum) != 0))
128        throw Exception("Elf invalid shoff and shnum combination");
129    if (ULEV(ehdr->e_shoff) != 0 && ULEV(ehdr->e_shstrndx) != SHN_UNDEF)
130    {   /* indexing of sections */
131        if (ULEV(ehdr->e_shoff) > binaryCodeSize)
132            throw Exception("SectionHeaders offset out of range!");
133        if (usumGt(ULEV(ehdr->e_shoff),
134                  ((typename Types::Word)ULEV(ehdr->e_shentsize))*ULEV(ehdr->e_shnum),
135                  binaryCodeSize))
136            throw Exception("SectionHeaders offset+size out of range!");
137        if (ULEV(ehdr->e_shstrndx) >= ULEV(ehdr->e_shnum))
138            throw Exception("Shstrndx out of range!");
139       
140        typename Types::Shdr& shstrShdr = getSectionHeader(ULEV(ehdr->e_shstrndx));
141        sectionStringTable = binaryCode + ULEV(shstrShdr.sh_offset);
142        const size_t unfinishedShstrPos = unfinishedRegionOfStringTable(
143                    sectionStringTable, ULEV(shstrShdr.sh_size));
144       
145        const typename Types::Shdr* symTableHdr = nullptr;
146        const typename Types::Shdr* dynSymTableHdr = nullptr;
147        const typename Types::Shdr* noteTableHdr = nullptr;
148        const typename Types::Shdr* dynamicTableHdr = nullptr;
149       
150        cxuint shnum = ULEV(ehdr->e_shnum);
151        if ((creationFlags & ELF_CREATE_SECTIONMAP) != 0)
152            sectionIndexMap.resize(shnum);
153        for (cxuint i = 0; i < shnum; i++)
154        {
155            const typename Types::Shdr& shdr = getSectionHeader(i);
156            /// checking section offset ranges
157            if (ULEV(shdr.sh_offset) > binaryCodeSize)
158                throw Exception("Section offset out of range!");
159            if (ULEV(shdr.sh_type) != SHT_NOBITS)
160                if (usumGt(ULEV(shdr.sh_offset), ULEV(shdr.sh_size), binaryCodeSize))
161                    throw Exception("Section offset+size out of range!");
162            if (ULEV(shdr.sh_link) >= ULEV(ehdr->e_shnum))
163                throw Exception("Section link out of range!");
164           
165            const typename Types::Size sh_nameindx = ULEV(shdr.sh_name);
166            if (sh_nameindx >= ULEV(shstrShdr.sh_size))
167                throw Exception("Section name index out of range!");
168           
169            if (sh_nameindx >= unfinishedShstrPos)
170                throw Exception("Unfinished section name!");
171           
172            const char* shname =
173                reinterpret_cast<const char*>(sectionStringTable + sh_nameindx);
174           
175            if ((creationFlags & ELF_CREATE_SECTIONMAP) != 0)
176                sectionIndexMap[i] = std::make_pair(shname, i);
177            // set symbol table and dynamic symbol table pointers
178            if (ULEV(shdr.sh_type) == SHT_SYMTAB)
179                symTableHdr = &shdr;
180            if (ULEV(shdr.sh_type) == SHT_DYNSYM)
181                dynSymTableHdr = &shdr;
182            if (ULEV(shdr.sh_type) == SHT_NOTE)
183                noteTableHdr = &shdr;
184            if (ULEV(shdr.sh_type) == SHT_DYNAMIC)
185                dynamicTableHdr = &shdr;
186        }
187        if ((creationFlags & ELF_CREATE_SECTIONMAP) != 0)
188            mapSort(sectionIndexMap.begin(), sectionIndexMap.end(), CStringLess());
189       
190        if (symTableHdr != nullptr)
191        {   // indexing symbols
192            if (ULEV(symTableHdr->sh_entsize) < sizeof(typename Types::Sym))
193                throw Exception("SymTable entry size is too small!");
194           
195            symbolEntSize = ULEV(symTableHdr->sh_entsize);
196            symbolTable = binaryCode + ULEV(symTableHdr->sh_offset);
197            if (ULEV(symTableHdr->sh_link) == SHN_UNDEF)
198                throw Exception("Symbol table doesn't have string table");
199           
200            typename Types::Shdr& symstrShdr = getSectionHeader(ULEV(symTableHdr->sh_link));
201            symbolStringTable = binaryCode + ULEV(symstrShdr.sh_offset);
202           
203            const size_t unfinishedSymstrPos = unfinishedRegionOfStringTable(
204                    symbolStringTable, ULEV(symstrShdr.sh_size));
205            symbolsNum = ULEV(symTableHdr->sh_size)/ULEV(symTableHdr->sh_entsize);
206            if ((creationFlags & ELF_CREATE_SYMBOLMAP) != 0)
207                symbolIndexMap.resize(symbolsNum);
208           
209            for (typename Types::Size i = 0; i < symbolsNum; i++)
210            {   /* verify symbol names */
211                const typename Types::Sym& sym = getSymbol(i);
212                const typename Types::Size symnameindx = ULEV(sym.st_name);
213                if (symnameindx >= ULEV(symstrShdr.sh_size))
214                    throw Exception("Symbol name index out of range!");
215                // check whether name is finished in string section content
216                if (symnameindx >= unfinishedSymstrPos)
217                    throw Exception("Unfinished symbol name!");
218               
219                const char* symname =
220                    reinterpret_cast<const char*>(symbolStringTable + symnameindx);
221                // add to symbol map
222                if ((creationFlags & ELF_CREATE_SYMBOLMAP) != 0)
223                    symbolIndexMap[i] = std::make_pair(symname, i);
224            }
225            if ((creationFlags & ELF_CREATE_SYMBOLMAP) != 0)
226                mapSort(symbolIndexMap.begin(), symbolIndexMap.end(), CStringLess());
227        }
228        if (dynSymTableHdr != nullptr)
229        {   // indexing dynamic symbols
230            if (ULEV(dynSymTableHdr->sh_entsize) < sizeof(typename Types::Sym))
231                throw Exception("DynSymTable entry size is too small!");
232           
233            dynSymEntSize = ULEV(dynSymTableHdr->sh_entsize);
234            dynSymTable = binaryCode + ULEV(dynSymTableHdr->sh_offset);
235            if (ULEV(dynSymTableHdr->sh_link) == SHN_UNDEF)
236                throw Exception("DynSymbol table doesn't have string table");
237           
238            typename Types::Shdr& dynSymstrShdr =
239                    getSectionHeader(ULEV(dynSymTableHdr->sh_link));
240            dynSymbolsNum = ULEV(dynSymTableHdr->sh_size)/ULEV(dynSymTableHdr->sh_entsize);
241           
242            dynSymStringTable = binaryCode + ULEV(dynSymstrShdr.sh_offset);
243            const size_t unfinishedSymstrPos = unfinishedRegionOfStringTable(
244                    dynSymStringTable, ULEV(dynSymstrShdr.sh_size));
245           
246            if ((creationFlags & ELF_CREATE_DYNSYMMAP) != 0)
247                dynSymIndexMap.resize(dynSymbolsNum);
248           
249            for (typename Types::Size i = 0; i < dynSymbolsNum; i++)
250            {   /* verify symbol names */
251                const typename Types::Sym& sym = getDynSymbol(i);
252                const typename Types::Size symnameindx = ULEV(sym.st_name);
253                if (symnameindx >= ULEV(dynSymstrShdr.sh_size))
254                    throw Exception("DynSymbol name index out of range!");
255                // check whether name is finished in string section content
256                if (symnameindx >= unfinishedSymstrPos)
257                    throw Exception("Unfinished dynsymbol name!");
258               
259                const char* symname =
260                    reinterpret_cast<const char*>(dynSymStringTable + symnameindx);
261                // add to symbol map
262                if ((creationFlags & ELF_CREATE_DYNSYMMAP) != 0)
263                    dynSymIndexMap[i] = std::make_pair(symname, i);
264            }
265            if ((creationFlags & ELF_CREATE_DYNSYMMAP) != 0)
266                mapSort(dynSymIndexMap.begin(), dynSymIndexMap.end(), CStringLess());
267        }
268        if (noteTableHdr != nullptr)
269        {
270            noteTable = binaryCode + ULEV(noteTableHdr->sh_offset);
271            noteTableSize = ULEV(noteTableHdr->sh_size);
272        }
273        if (dynamicTableHdr != nullptr)
274        {
275            dynamicTable = binaryCode + ULEV(dynamicTableHdr->sh_offset);
276            const typename Types::Size entSize = ULEV(dynamicTableHdr->sh_entsize);
277            const typename Types::Size size = ULEV(dynamicTableHdr->sh_size);
278            if (entSize < sizeof(typename Types::Dyn))
279                throw Exception("Size of dynamic entry is too small!");
280            if (size % entSize != 0)
281                throw Exception("Size of dynamic section is not match!");
282            dynamicsNum = entSize / size;
283            dynamicEntSize = entSize;
284        }
285    }
286}
287
288template<typename Types>
289uint16_t ElfBinaryTemplate<Types>::getSectionIndex(const char* name) const
290{
291    if (hasSectionMap())
292    {
293        SectionIndexMap::const_iterator it = binaryMapFind(
294                    sectionIndexMap.begin(), sectionIndexMap.end(), name, CStringLess());
295        if (it == sectionIndexMap.end())
296            throw Exception(std::string("Can't find Elf")+Types::bitName+" Section");
297        return it->second;
298    }
299    else
300    {
301        for (cxuint i = 0; i < getSectionHeadersNum(); i++)
302        {
303            if (::strcmp(getSectionName(i), name) == 0)
304                return i;
305        }
306        throw Exception(std::string("Can't find Elf")+Types::bitName+" Section");
307    }
308}
309
310template<typename Types>
311typename Types::Size ElfBinaryTemplate<Types>::getSymbolIndex(const char* name) const
312{
313    SymbolIndexMap::const_iterator it = binaryMapFind(
314                    symbolIndexMap.begin(), symbolIndexMap.end(), name, CStringLess());
315    if (it == symbolIndexMap.end())
316        throw Exception(std::string("Can't find Elf")+Types::bitName+" Symbol");
317    return it->second;
318}
319
320template<typename Types>
321typename Types::Size ElfBinaryTemplate<Types>::getDynSymbolIndex(const char* name) const
322{
323    SymbolIndexMap::const_iterator it = binaryMapFind(
324                    dynSymIndexMap.begin(), dynSymIndexMap.end(), name, CStringLess());
325    if (it == dynSymIndexMap.end())
326        throw Exception(std::string("Can't find Elf")+Types::bitName+" DynSymbol");
327    return it->second;
328}
329
330template class CLRX::ElfBinaryTemplate<CLRX::Elf32Types>;
331template class CLRX::ElfBinaryTemplate<CLRX::Elf64Types>;
332
333bool CLRX::isElfBinary(size_t binarySize, const cxbyte* binary)
334{
335    if (binarySize < sizeof(Elf32_Ehdr) ||
336        ULEV(*reinterpret_cast<const uint32_t*>(binary)) != elfMagicValue)
337        return false;
338    if ((binary[EI_CLASS] != ELFCLASS32 && binary[EI_CLASS] != ELFCLASS64) ||
339        binary[EI_DATA] != ELFDATA2LSB) // only LSB elf is supported
340        return false;
341    if ((binary[EI_CLASS] == ELFCLASS32 && binarySize < sizeof(Elf32_Ehdr)) ||
342        (binary[EI_CLASS] == ELFCLASS64 && binarySize < sizeof(Elf64_Ehdr)))
343        return false;
344    if (ULEV(*((const uint64_t*)(binary+8))) != 0)
345        return false;
346    return true;
347}
348
349/*
350 * Elf binary generator
351 */
352
353uint16_t CLRX::convertSectionId(cxuint sectionIndex, const uint16_t* builtinSections,
354                  cxuint maxBuiltinSection, cxuint extraSectionIndex)
355{
356    if (sectionIndex == ELFSECTID_NULL)
357        return 0;
358    if (sectionIndex == ELFSECTID_ABS)
359        return SHN_ABS;
360    if (sectionIndex == ELFSECTID_UNDEF)
361        return SHN_UNDEF;
362    if (sectionIndex < ELFSECTID_START)
363        return sectionIndex+extraSectionIndex;
364    else if (sectionIndex >= ELFSECTID_START && sectionIndex <= maxBuiltinSection)
365    {
366        const uint16_t shndx = builtinSections[sectionIndex-ELFSECTID_START];
367        if (shndx == SHN_UNDEF) // if table entry for sectionIndex is not defined
368            throw Exception("Wrong BinSection:sectionId");
369        return builtinSections[sectionIndex-ELFSECTID_START];
370    }
371    else // failed
372        throw Exception("Wrong BinSection:sectionId");
373}
374
375ElfRegionContent::~ElfRegionContent()
376{ }
377
378template<typename Types>
379static std::unique_ptr<uint32_t[]> calculateHashValuesForSymbols(bool addNullSymbol,
380            const std::vector<ElfSymbolTemplate<Types> >& symbols)
381{
382    const size_t symsNum = symbols.size() + addNullSymbol;
383    std::unique_ptr<uint32_t[]> hashCodes(new uint32_t[symsNum]);
384    if (addNullSymbol)
385        hashCodes[0] = 0;
386    for (size_t i = 0; i < symbols.size(); i++)
387    {
388        uint32_t h = 0, g;
389        const cxbyte* name = reinterpret_cast<const cxbyte*>(symbols[i].name);
390        while(*name!=0)
391        {
392            h = (h<<4) + *name++;
393            g = h & 0xf0000000U;
394            if (g) h ^= g>>24;
395            h &= ~g;
396        }
397        hashCodes[i+addNullSymbol] = h;
398    }
399    return hashCodes;
400}
401
402/// return bucket number
403static uint32_t optimizeHashBucketsNum(uint32_t hashNum, bool skipFirst,
404                           const uint32_t* hashCodes)
405{
406    uint32_t bestBucketNum = 0;
407    uint64_t bestValue = UINT64_MAX;
408    uint32_t firstStep = std::max(uint32_t(hashNum>>2), 1U);
409    uint64_t maxSteps = (uint64_t(hashNum)<<1) - (firstStep) + 1;
410    const uint32_t steps = (maxSteps<=1000U) ? maxSteps :
411                hashNum<<((32-CLZ32(hashNum))>>1);
412   
413    std::unique_ptr<uint32_t[]> chainLengths(new uint32_t[(hashNum<<2)+1]);
414    const uint32_t stepSize = maxSteps / steps;
415    for (uint32_t buckets = firstStep; buckets <= (hashNum<<1); buckets += stepSize)
416    {   //
417        std::fill(chainLengths.get(), chainLengths.get() + buckets, 0U);
418        // calculate chain lengths
419        for (size_t i = skipFirst; i < hashNum; i++)
420            chainLengths[hashCodes[i] % buckets]++;
421        /// value, smaller is better
422        uint64_t value = uint64_t(buckets);
423        for (uint32_t i = 0; i < buckets; i++)
424            value += chainLengths[i]*chainLengths[i];
425        if (value < bestValue)
426        {
427            bestBucketNum = buckets;
428            bestValue = value;
429        }
430    }
431    return bestBucketNum;
432}
433
434template<typename Types>
435ElfBinaryGenTemplate<Types>::ElfBinaryGenTemplate()
436        : sizeComputed(false), addNullSym(true), addNullDynSym(true), addNullSection(true),
437          addrStartRegion(0), shStrTab(0), strTab(0), dynStr(0), shdrTabRegion(0),
438          phdrTabRegion(0), bucketsNum(0), isHashDynSym(false)
439{ }
440
441template<typename Types>
442ElfBinaryGenTemplate<Types>::ElfBinaryGenTemplate(const ElfHeaderTemplate<Types>& _header,
443            bool _addNullSym, bool _addNullDynSym, bool _addNullSection,
444            cxuint addrCountingFromRegion)
445        : sizeComputed(false), addNullSym(_addNullSym), addNullDynSym(_addNullDynSym),
446          addNullSection(_addNullSection),  addrStartRegion(addrCountingFromRegion),
447          shStrTab(0), strTab(0), dynStr(0), shdrTabRegion(0), phdrTabRegion(0),
448          header(_header), bucketsNum(0), isHashDynSym(false)
449{ }
450
451template<typename Types>
452void ElfBinaryGenTemplate<Types>::addRegion(const ElfRegionTemplate<Types>& region)
453{ regions.push_back(region); }
454
455template<typename Types>
456void ElfBinaryGenTemplate<Types>::addProgramHeader(
457            const ElfProgramHeaderTemplate<Types>& progHeader)
458{ progHeaders.push_back(progHeader); }
459
460static const int32_t dynTableSize = DT_NUM;
461
462
463template<typename Types>
464static inline typename Types::Word resolveSectionAddress(
465        const ElfHeaderTemplate<Types>& header, const ElfRegionTemplate<Types>& region2,
466        typename Types::Word regionAddr)
467{   /* addrBase is base address of first section. if not defined
468     * use address base as virtual address base from elf header */
469    if (region2.section.addrBase==Types::nobase)
470        return regionAddr;
471    else if (region2.section.addrBase != 0)
472        return region2.section.addrBase+regionAddr;
473    else if (header.vaddrBase != 0)
474        return header.vaddrBase+regionAddr;
475    else
476        return 0;
477}
478
479template<typename Types>
480void ElfBinaryGenTemplate<Types>::computeSize()
481{
482    if (sizeComputed) return;
483   
484    /* verify data */
485    if (header.entryRegion != UINT_MAX && header.entryRegion >= regions.size())
486        throw Exception("Header entry region out of range");
487   
488    regionOffsets.reset(new typename Types::Word[regions.size()]);
489    regionAddresses.reset(new typename Types::Word[regions.size()]);
490    size = sizeof(typename Types::Ehdr);
491    sectionsNum = addNullSection; // if add null section
492    cxuint hashSymSectionIdx = UINT_MAX;
493    bool haveDynamic = false;
494    for (const auto& region: regions)
495        if (region.type == ElfRegionType::SECTION)
496        {
497            if (region.section.type==SHT_HASH)
498                hashSymSectionIdx = region.section.link;
499            else if (region.section.type==SHT_DYNAMIC)
500                haveDynamic = true;
501            sectionsNum++;
502        }
503   
504    /// determine symbol name
505    cxuint sectionCount = addNullSection;
506    isHashDynSym = false;
507    if (hashSymSectionIdx!=UINT_MAX)
508    {
509        bool hashSymDetected = false;
510        for (const auto& region: regions)
511            if (region.type == ElfRegionType::SECTION)
512            {
513                if (hashSymSectionIdx==sectionCount)
514                {   // get smybol section
515                    if (region.section.type==SHT_SYMTAB)
516                    {
517                        isHashDynSym = false;
518                        hashSymDetected = true;
519                    }
520                    else if (region.section.type==SHT_DYNSYM)
521                    {
522                        isHashDynSym = true;
523                        hashSymDetected = true;
524                    }
525                    else
526                        throw Exception("Wrong Hash Sym section!");
527                }
528                sectionCount++;
529            }
530        if (!hashSymDetected)
531            throw Exception("Wrong Hash Sym is not detected!");
532    }
533   
534    sectionRegions.reset(new cxuint[sectionsNum+1]);
535    sectionRegions[0] = UINT_MAX;
536    sectionCount = addNullSection;
537    typename Types::Word address = (addrStartRegion==PHREGION_FILESTART) ? size : 0;
538   
539    std::unique_ptr<typename Types::Word[]> dynValTable;
540    if (haveDynamic)
541    {   // prepare dynamic structures
542        dynamicValues.reset(new typename Types::Word[dynamics.size()]);
543        dynValTable.reset(new typename Types::Word[dynTableSize]);
544    }
545   
546    for (const auto& sym: symbols)
547        if (sym.sectionIndex >= sectionsNum)
548            throw Exception("Symbol section index out of range");
549    for (const auto& sym: dynSymbols)
550        if (sym.sectionIndex >= sectionsNum)
551            throw Exception("DynSymbol section index out of range");
552   
553    for (size_t i = 0; i < regions.size(); i++)
554    {
555        ElfRegionTemplate<Types>& region = regions[i];
556        if (region.align > 1)
557        {   // fix alignment
558            if ((size&(region.align-1))!=0)
559                size += region.align - (size&(region.align-1));
560            if ((address&(region.align-1))!=0)
561                address += region.align - (address&(region.align-1));
562        }
563       
564        regionOffsets[i] = size;
565        regionAddresses[i] = address;
566        // add region size
567        if (region.type == ElfRegionType::PHDR_TABLE)
568        {
569            size += uint64_t(progHeaders.size())*sizeof(typename Types::Phdr);
570            region.size = size-regionOffsets[i];
571            phdrTabRegion = i;
572            for (const auto& progHdr: progHeaders)
573            {
574                if (progHdr.regionStart!=PHREGION_FILESTART &&
575                            progHdr.regionStart >= regions.size())
576                    throw Exception("Region start out of range");
577                if ((progHdr.regionStart==PHREGION_FILESTART &&
578                     progHdr.regionsNum > regions.size()) ||
579                    (progHdr.regionStart!=PHREGION_FILESTART &&
580                     uint64_t(progHdr.regionStart) + progHdr.regionsNum > regions.size()))
581                    throw Exception("Region end out of range");
582            }
583            if (addrStartRegion==PHREGION_FILESTART)
584                address = size;
585        }
586        else if (region.type == ElfRegionType::SHDR_TABLE)
587        {
588            size += uint64_t(sectionsNum)*sizeof(typename Types::Shdr);
589            region.size = size-regionOffsets[i];
590            shdrTabRegion = i;
591            if (addrStartRegion==PHREGION_FILESTART)
592                address = size;
593        }
594        else if (region.type == ElfRegionType::USER)
595        {
596            if (addrStartRegion==PHREGION_FILESTART)
597                address = size;
598            size += region.size;
599        }
600        else if (region.type == ElfRegionType::SECTION)
601        {   // if section
602            if (region.section.link >= sectionsNum)
603                throw Exception("Section link out of range");
604           
605            if (haveDynamic)
606            {
607                switch(region.section.type)
608                {
609                    case SHT_DYNSYM:
610                        dynValTable[DT_SYMTAB] = resolveSectionAddress(header, region,
611                                   regionAddresses[i]);
612                        dynValTable[DT_SYMENT] = sizeof(typename Types::Sym);
613                        break;
614                    case SHT_STRTAB:
615                        if (::strcmp(region.section.name, ".dynstr")==0)
616                            dynValTable[DT_STRTAB] = resolveSectionAddress(header, region,
617                                   regionAddresses[i]);
618                        break;
619                    case SHT_HASH:
620                        dynValTable[DT_HASH] = resolveSectionAddress(header, region,
621                                 regionAddresses[i]);
622                        break;
623                }
624            }
625           
626            if (region.section.type != SHT_NOBITS && region.size != 0)
627                size += region.size;
628            else // otherwise get default size for symtab, dynsym, strtab, dynstr
629            {
630                if (region.section.type == SHT_SYMTAB)
631                    size += uint64_t(symbols.size()+addNullSym)*
632                                sizeof(typename Types::Sym);
633                else if (region.section.type == SHT_DYNSYM)
634                    size += uint64_t(dynSymbols.size()+addNullDynSym)*
635                                sizeof(typename Types::Sym);
636                else if (region.section.type == SHT_HASH)
637                {
638                    const std::vector<ElfSymbolTemplate<Types> >& hashSymbols = 
639                        (isHashDynSym) ? dynSymbols : symbols;
640                    bool addNullHashSym = (isHashDynSym) ? addNullDynSym : addNullSym;
641                    hashCodes = calculateHashValuesForSymbols(addNullDynSym, hashSymbols);
642                    bucketsNum = optimizeHashBucketsNum(hashSymbols.size()+addNullHashSym,
643                           addNullHashSym, hashCodes.get());
644                    size += 4*(bucketsNum + hashSymbols.size()+addNullHashSym + 2);
645                }
646                else if (region.section.type == SHT_DYNAMIC)
647                    size += (dynamics.size()+1) * sizeof(typename Types::Dyn);
648                else if (region.section.type == SHT_NOTE)
649                {
650                    for (const ElfNote& note: notes)
651                    {   // note size with data
652                        size_t nameSize = ::strlen(note.name)+1;
653                        if ((nameSize&3)!=0)
654                            nameSize += 4 - (nameSize&3);
655                        size_t descSize = note.descSize;
656                        if ((descSize&3)!=0)
657                            descSize += 4 - (descSize&3);
658                        size += sizeof(typename Types::Nhdr) + nameSize + descSize;
659                    }
660                }
661                else if (region.section.type == SHT_STRTAB)
662                {
663                    if (::strcmp(region.section.name, ".strtab") == 0)
664                    {
665                        size += (addNullSym);
666                        for (const auto& sym: symbols)
667                            if (sym.name != nullptr && sym.name[0] != 0)
668                                size += ::strlen(sym.name)+1;
669                    }
670                    else if (::strcmp(region.section.name, ".dynstr") == 0)
671                    {
672                        size += (addNullDynSym);
673                        for (const auto& sym: dynSymbols)
674                            if (sym.name != nullptr && sym.name[0] != 0)
675                                size += ::strlen(sym.name)+1;
676                    }
677                    else if (::strcmp(region.section.name, ".shstrtab") == 0)
678                    {
679                        size += (addNullSection);
680                        for (const auto& region2: regions)
681                        {
682                            if (region2.type == ElfRegionType::SECTION &&
683                                region2.section.name != nullptr &&
684                                region2.section.name[0] != 0)
685                                size += ::strlen(region2.section.name)+1;
686                        }
687                    }
688                }
689                if (region.section.type != SHT_NOBITS)
690                    region.size = size-regionOffsets[i];
691            }
692            if (addrStartRegion==PHREGION_FILESTART)
693                address = size;
694            else if (i >= addrStartRegion) // begin counting address from that region
695                address += region.size;
696           
697            if (haveDynamic)
698            {
699                if (region.section.type == SHT_STRTAB &&
700                    ::strcmp(region.section.name, ".dynstr") == 0)
701                    dynValTable[DT_STRSZ] = region.size;
702            }
703           
704            if (::strcmp(region.section.name, ".strtab") == 0)
705                strTab = sectionCount;
706            else if (::strcmp(region.section.name, ".dynstr") == 0)
707                dynStr = sectionCount;
708            else if (::strcmp(region.section.name, ".shstrtab") == 0)
709                shStrTab = sectionCount;
710            sectionRegions[sectionCount] = i;
711            sectionCount++;
712        }
713    }
714   
715    if (haveDynamic)
716    {   // set dynamic values
717        for (size_t i = 0; i < dynamics.size(); i++)
718            if (dynamics[i] >= 0 && dynamics[i] < dynTableSize)
719                dynamicValues[i] = dynValTable[dynamics[i]];
720    }
721   
722    sizeComputed = true;
723}
724
725template<typename Types>
726uint64_t ElfBinaryGenTemplate<Types>::countSize()
727{
728    computeSize();
729    return size;
730}
731
732static void createHashTable(uint32_t bucketsNum, uint32_t hashNum, bool skipFirst,
733                           const uint32_t* hashCodes, uint32_t* output)
734{
735    SLEV(output[0], bucketsNum);
736    SLEV(output[1], hashNum);
737    uint32_t* buckets = output + 2;
738    uint32_t* chains = output + bucketsNum + 2;
739    std::fill(buckets, buckets + bucketsNum, 0U);
740    std::fill(chains, chains + hashNum, STN_UNDEF);
741   
742    std::unique_ptr<uint32_t[]> lastNodes(new uint32_t[bucketsNum]);
743    std::fill(lastNodes.get(), lastNodes.get() + bucketsNum, UINT32_MAX);
744    for (uint32_t i = skipFirst; i < hashNum; i++)
745    {
746        const uint32_t bucket = hashCodes[i] % bucketsNum;
747        if (lastNodes[bucket] == UINT32_MAX)
748        {   // first entry of chain
749            SLEV(buckets[bucket], i);
750            lastNodes[bucket] = i;
751        }
752        else
753        {
754            SLEV(chains[lastNodes[bucket]], i);
755            lastNodes[bucket] = i;
756        }
757    }
758}
759
760template<typename Types>
761void ElfBinaryGenTemplate<Types>::generate(FastOutputBuffer& fob)
762{
763    computeSize();
764    const uint64_t startOffset = fob.getWritten();
765    /* write elf header */
766    {
767        typename Types::Ehdr ehdr;
768        ::memset(ehdr.e_ident, 0, EI_NIDENT);
769        ehdr.e_ident[0] = 0x7f;
770        ehdr.e_ident[1] = 'E';
771        ehdr.e_ident[2] = 'L';
772        ehdr.e_ident[3] = 'F';
773        ehdr.e_ident[4] = Types::ELFCLASS;
774        ehdr.e_ident[5] = ELFDATA2LSB;
775        ehdr.e_ident[6] = EV_CURRENT;
776        ehdr.e_ident[EI_OSABI] = header.osABI;
777        ehdr.e_ident[EI_ABIVERSION] = header.abiVersion;
778        SLEV(ehdr.e_type, header.type);
779        SLEV(ehdr.e_machine, header.machine);
780        SLEV(ehdr.e_version, header.version);
781        SLEV(ehdr.e_flags, header.flags);
782        if (header.entryRegion != UINT_MAX)
783        {   // if have entry
784            typename Types::Word entry = regionOffsets[header.entryRegion] + header.entry;
785            if (regions[header.entryRegion].type == ElfRegionType::SECTION &&
786                regions[header.entryRegion].section.addrBase != 0)
787                entry += regions[header.entryRegion].section.addrBase;
788            else
789                entry += header.vaddrBase;
790           
791            SLEV(ehdr.e_entry, entry);
792        }
793        else
794            SLEV(ehdr.e_entry, 0);
795        SLEV(ehdr.e_ehsize, sizeof(typename Types::Ehdr));
796        if (!progHeaders.empty())
797        {
798            SLEV(ehdr.e_phentsize, sizeof(typename Types::Phdr));
799            SLEV(ehdr.e_phoff, regionOffsets[phdrTabRegion]);
800        }
801        else
802        {
803            SLEV(ehdr.e_phentsize, 0);
804            SLEV(ehdr.e_phoff, 0);
805        }
806        SLEV(ehdr.e_phnum, progHeaders.size());
807        SLEV(ehdr.e_shentsize, sizeof(typename Types::Shdr));
808        SLEV(ehdr.e_shnum, sectionsNum);
809        SLEV(ehdr.e_shoff, regionOffsets[shdrTabRegion]);
810        SLEV(ehdr.e_shstrndx, shStrTab);
811       
812        fob.writeObject(ehdr);
813    }
814   
815    size_t nullSymNameOffset = 0;
816    // if addNullSym is not set, then no empty symbol name added, then we
817    // find first null character
818    if (!addNullSym && !symbols.empty())
819        nullSymNameOffset = ::strlen(symbols[0].name);
820    size_t nullDynSymNameOffset = 0;
821    // if addNullDynSym is not set, then no empty dynamic symbol name added, then we
822    // find first null character
823    if (!addNullDynSym && !dynSymbols.empty())
824        nullDynSymNameOffset = ::strlen(dynSymbols[0].name);
825    // if addNullSection is not set, then no empty section name added, then we
826    // find first null character
827    size_t nullSectionNameOffset = 0;
828    if (!addNullSection)
829    {
830        for (const ElfRegionTemplate<Types>& reg: regions)
831            if (reg.type == ElfRegionType::SECTION)
832            {
833                nullSectionNameOffset = ::strlen(reg.section.name);
834                break;
835            }
836    }
837   
838    /* write regions */
839    for (size_t i = 0; i < regions.size(); i++)
840    {   
841        const ElfRegionTemplate<Types>& region = regions[i];
842        // fix alignment
843        uint64_t toFill = 0;
844        typename Types::Word ralign = (region.type==ElfRegionType::SECTION) ?
845                        region.section.align : 0;
846        ralign = std::max(region.align, ralign);
847        if (ralign > 1)
848        {
849            const uint64_t curOffset = (fob.getWritten()-startOffset);
850            if (ralign!=0 && (curOffset&(ralign-1))!=0)
851                toFill = ralign - (curOffset&(ralign-1));
852            fob.fill(toFill, 0);
853        }
854        assert(regionOffsets[i] == fob.getWritten()-startOffset);
855       
856        // write content
857        if (region.type == ElfRegionType::PHDR_TABLE)
858        {   /* write program headers */
859            for (const auto& progHeader: progHeaders)
860            {
861                typename Types::Phdr phdr;
862                SLEV(phdr.p_type, progHeader.type);
863                SLEV(phdr.p_flags, progHeader.flags);
864                const ElfRegionTemplate<Types> startRegion(sizeof(typename Types::Ehdr),
865                        (const cxbyte*)nullptr, sizeof(typename Types::Word));
866               
867                const ElfRegionTemplate<Types>& sregion = 
868                        (progHeader.regionStart==PHREGION_FILESTART) ? startRegion :
869                        regions[progHeader.regionStart];
870                const cxuint rstart = (progHeader.regionStart!=PHREGION_FILESTART) ?
871                            progHeader.regionStart : 0;
872                const typename Types::Word sroffset =
873                        (progHeader.regionStart!=PHREGION_FILESTART) ?
874                            regionOffsets[progHeader.regionStart] : 0;
875                const typename Types::Word sraddress =
876                        (progHeader.regionStart!=PHREGION_FILESTART) ?
877                            regionAddresses[progHeader.regionStart] : 0;
878               
879                bool zeroOffset = sregion.type == ElfRegionType::SECTION &&
880                        sregion.section.zeroOffset;
881                SLEV(phdr.p_offset, !zeroOffset ? sroffset : 0);
882                if (progHeader.align==0)
883                {
884                    typename Types::Word align = (sregion.type==ElfRegionType::SECTION) ?
885                            sregion.section.align : 0;
886                    align = std::max(sregion.align, align);
887                    SLEV(phdr.p_align, align);
888                }
889                else
890                    SLEV(phdr.p_align, progHeader.align);
891               
892                /* paddrBase and vaddrBase is base to program header virtual and physical
893                 * addresses for program header. if not defined then get address base
894                 * from ELF header */
895                if (progHeader.paddrBase == Types::nobase)
896                    SLEV(phdr.p_paddr, sraddress);
897                else if (progHeader.paddrBase != 0)
898                    SLEV(phdr.p_paddr, progHeader.paddrBase + sraddress);
899                else if (header.paddrBase != 0)
900                    SLEV(phdr.p_paddr, header.paddrBase + sraddress);
901                else
902                    SLEV(phdr.p_paddr, 0);
903               
904                if (progHeader.vaddrBase == Types::nobase)
905                    SLEV(phdr.p_vaddr, sraddress);
906                else if (progHeader.vaddrBase != 0)
907                    SLEV(phdr.p_vaddr, progHeader.vaddrBase + sraddress);
908                else if (header.vaddrBase != 0)
909                    SLEV(phdr.p_vaddr, header.vaddrBase + sraddress);
910                else
911                    SLEV(phdr.p_vaddr, 0);
912               
913                // last region size for file - if nobits section then we assume zero size
914                if (progHeader.regionsNum!=0)
915                {
916                    const auto& lastReg = regions[rstart + progHeader.regionsNum-1];
917                    uint64_t fileLastRegSize =(lastReg.type!=ElfRegionType::SECTION ||
918                        lastReg.section.type!=SHT_NOBITS) ? lastReg.size : 0;
919                    /// fileSize - add offset of first region to simulate region alignment
920                    const typename Types::Word fileSize = regionOffsets[rstart+
921                            progHeader.regionsNum-1] + fileLastRegSize - sroffset;
922                    const typename Types::Word phSize = regionAddresses[rstart+
923                            progHeader.regionsNum-1]+regions[rstart+
924                            progHeader.regionsNum-1].size - sraddress;
925                   
926                    if (progHeader.haveMemSize)
927                    {
928                        if (progHeader.memSize != 0)
929                            SLEV(phdr.p_memsz, progHeader.memSize);
930                        else
931                            SLEV(phdr.p_memsz, phSize);
932                    }
933                    else
934                        SLEV(phdr.p_memsz, 0);
935                    SLEV(phdr.p_filesz, fileSize);
936                }
937                else
938                {
939                    SLEV(phdr.p_memsz, 0);
940                    SLEV(phdr.p_filesz, 0);
941                }
942                fob.writeObject(phdr);
943            }
944        }
945        else if (region.type == ElfRegionType::SHDR_TABLE)
946        {   /* write section headers table */
947            if (addNullSection)
948                fob.fill(sizeof(typename Types::Shdr), 0);
949            uint32_t nameOffset = (addNullSection);
950            for (cxuint j = 0; j < regions.size(); j++)
951            {
952                const auto& region2 = regions[j];
953                if (region2.type == ElfRegionType::SECTION)
954                {
955                    typename Types::Shdr shdr;
956                    if (region2.section.name!=nullptr && region2.section.name[0]!=0)
957                        SLEV(shdr.sh_name, nameOffset);
958                    else // set empty name offset
959                        SLEV(shdr.sh_name, nullSectionNameOffset);
960                    SLEV(shdr.sh_type, region2.section.type);
961                    SLEV(shdr.sh_flags, region2.section.flags);
962                    SLEV(shdr.sh_offset, (!region2.section.zeroOffset) ?
963                                regionOffsets[j] : 0);
964                    SLEV(shdr.sh_addr, resolveSectionAddress(header, region2,
965                                     regionAddresses[j]));
966                   
967                    if (region2.align != 0 || j+1 >= regions.size() ||
968                        regionOffsets[j]+region2.size == regionOffsets[j+1])
969                        SLEV(shdr.sh_size, region2.size);
970                    else
971                        SLEV(shdr.sh_size, regionOffsets[j+1]-regionOffsets[j]);
972                    SLEV(shdr.sh_info, region2.section.info);
973                    SLEV(shdr.sh_addralign, (region2.section.align==0) ?
974                            region2.align : region2.section.align);
975                    if (region2.section.link == 0)
976                    {
977                        if (::strcmp(region2.section.name, ".symtab") == 0)
978                            SLEV(shdr.sh_link, strTab);
979                        else if (::strcmp(region2.section.name, ".dynsym") == 0)
980                            SLEV(shdr.sh_link, dynStr);
981                        else
982                            SLEV(shdr.sh_link, region2.section.link);
983                    }
984                    else
985                        SLEV(shdr.sh_link, region2.section.link);
986                   
987                    if (region2.section.type == SHT_SYMTAB ||
988                        region2.section.type == SHT_DYNSYM)
989                        SLEV(shdr.sh_entsize, sizeof(typename Types::Sym));
990                    else if (region2.section.type == SHT_DYNAMIC)
991                        SLEV(shdr.sh_entsize, sizeof(typename Types::Dyn));
992                    else
993                        SLEV(shdr.sh_entsize, region2.section.entSize);
994                    if (region2.section.name!=nullptr && region2.section.name[0]!=0)
995                        nameOffset += ::strlen(region2.section.name)+1;
996                    fob.writeObject(shdr);
997                }
998            }
999        }
1000        else if (region.type == ElfRegionType::USER)
1001        {
1002            if (region.dataFromPointer)
1003                fob.writeArray(region.size, region.data);
1004            else
1005                (*region.dataGen)(fob);
1006        }
1007        else if (region.type == ElfRegionType::SECTION)
1008        {
1009            if (region.data == nullptr)
1010            {
1011                if (region.section.type == SHT_SYMTAB || region.section.type == SHT_DYNSYM)
1012                {
1013                    uint32_t nameOffset = 0;
1014                    if (region.section.type == SHT_SYMTAB && addNullSym)
1015                    {
1016                        fob.fill(sizeof(typename Types::Sym), 0);
1017                        nameOffset = 1;
1018                    }
1019                    if (region.section.type == SHT_DYNSYM && addNullDynSym)
1020                    {
1021                        fob.fill(sizeof(typename Types::Sym), 0);
1022                        nameOffset = 1;
1023                    }
1024                    const auto& symbolsList = (region.section.type == SHT_SYMTAB) ?
1025                            symbols : dynSymbols;
1026                    for (const auto& inSym: symbolsList)
1027                    {
1028                        typename Types::Sym sym;
1029                        if (inSym.name != nullptr && inSym.name[0] != 0)
1030                            SLEV(sym.st_name, nameOffset);
1031                        else  // set empty name offset (symbol or dynamic symbol)
1032                            SLEV(sym.st_name, (region.section.type == SHT_SYMTAB) ?
1033                                        nullSymNameOffset : nullDynSymNameOffset);
1034                       
1035                        SLEV(sym.st_shndx, inSym.sectionIndex);
1036                        SLEV(sym.st_size, inSym.size);
1037                        /// if value defined as address
1038                        if (!inSym.valueIsAddr)
1039                            SLEV(sym.st_value, inSym.value);
1040                        // if not use conversion to address with section addrBase
1041                        else if ((inSym.sectionIndex != 0 || !addNullSection) &&
1042                                regions[sectionRegions[
1043                                    inSym.sectionIndex]].section.addrBase != 0)
1044                        {
1045                            typename Types::Word addrBase = regions[sectionRegions[
1046                                    inSym.sectionIndex]].section.addrBase;
1047                            SLEV(sym.st_value, inSym.value + regionOffsets[
1048                                    sectionRegions[inSym.sectionIndex]] +
1049                                    (addrBase!=Types::nobase ? addrBase : 0));
1050                        }
1051                        else if (header.vaddrBase!=Types::nobase)
1052                            // use elf headerf virtual address base
1053                            SLEV(sym.st_value, inSym.value + regionOffsets[
1054                                sectionRegions[inSym.sectionIndex]] +
1055                                (header.vaddrBase!=Types::nobase ? header.vaddrBase : 0));
1056                        sym.st_other = inSym.other;
1057                        sym.st_info = inSym.info;
1058                        if (inSym.name != nullptr && inSym.name[0] != 0)
1059                            nameOffset += ::strlen(inSym.name)+1;
1060                        fob.writeObject(sym);
1061                    }
1062                }
1063                else if (region.section.type == SHT_DYNAMIC)
1064                {   // dynamic table
1065                    typename Types::Dyn dyn;
1066                    for (size_t k = 0; k < dynamics.size(); k++)
1067                    {
1068                        SLEV(dyn.d_tag, dynamics[k]);
1069                        SLEV(dyn.d_un.d_val, dynamicValues[k]);
1070                        fob.writeObject(dyn);
1071                    }
1072                    SLEV(dyn.d_tag, DT_NULL);
1073                    SLEV(dyn.d_un.d_val, 0U);
1074                    fob.writeObject(dyn);
1075                }
1076                else if (region.section.type == SHT_HASH)
1077                {
1078                    const std::vector<ElfSymbolTemplate<Types> >& hashSymbols = 
1079                        (isHashDynSym) ? dynSymbols : symbols;
1080                    bool addNullHashSym = (isHashDynSym) ? addNullDynSym : addNullSym;
1081                    Array<uint32_t> hashTable(2 + hashSymbols.size() + addNullHashSym +
1082                                bucketsNum);
1083                    createHashTable(bucketsNum, hashSymbols.size()+addNullHashSym,
1084                                addNullHashSym, hashCodes.get(), hashTable.data());
1085                    fob.writeArray(hashTable.size(), hashTable.data());
1086                }
1087                else if (region.section.type == SHT_NOTE)
1088                {
1089                    for (const ElfNote& note: notes)
1090                    {
1091                        typename Types::Nhdr nhdr;
1092                        size_t nameSize = ::strlen(note.name)+1;
1093                        size_t descSize = note.descSize;
1094                        SLEV(nhdr.n_namesz, nameSize);
1095                        SLEV(nhdr.n_descsz, descSize);
1096                        SLEV(nhdr.n_type, note.type);
1097                        fob.writeObject(nhdr);
1098                        fob.write(nameSize, note.name);
1099                        if ((nameSize&3) != 0)
1100                            fob.fill(4 - (nameSize&3), 0);
1101                        fob.writeArray(descSize, note.desc);
1102                        if ((descSize&3) != 0)
1103                            fob.fill(4 - (descSize&3), 0);
1104                    }
1105                }
1106                else if (region.section.type == SHT_STRTAB)
1107                {
1108                    if (::strcmp(region.section.name, ".strtab") == 0)
1109                    {
1110                        if (addNullSym)
1111                            fob.put(0);
1112                        for (const auto& sym: symbols)
1113                            if (sym.name != nullptr && sym.name[0] != 0)
1114                                fob.write(::strlen(sym.name)+1, sym.name);
1115                    }
1116                    else if (::strcmp(region.section.name, ".dynstr") == 0)
1117                    {
1118                        if (addNullDynSym)
1119                            fob.put(0);
1120                        for (const auto& sym: dynSymbols)
1121                            if (sym.name != nullptr && sym.name[0] != 0)
1122                                fob.write(::strlen(sym.name)+1, sym.name);
1123                    }
1124                    else if (::strcmp(region.section.name, ".shstrtab") == 0)
1125                    {
1126                        if (addNullSection)
1127                            fob.put(0);
1128                        for (const auto& region2: regions)
1129                            if (region2.type == ElfRegionType::SECTION &&
1130                                region2.section.name != nullptr &&
1131                                region2.section.name[0] != 0)
1132                                fob.write(::strlen(region2.section.name)+1,
1133                                          region2.section.name);
1134                    }
1135                }
1136            }
1137            else if (region.section.type != SHT_NOBITS)
1138            {
1139                if (region.dataFromPointer)
1140                    fob.writeArray(region.size, region.data);
1141                else
1142                    (*region.dataGen)(fob);
1143            }
1144        }
1145    }
1146    fob.flush();
1147    fob.getOStream().flush();
1148    assert(size == fob.getWritten()-startOffset);
1149}
1150
1151template class CLRX::ElfBinaryGenTemplate<CLRX::Elf32Types>;
1152template class CLRX::ElfBinaryGenTemplate<CLRX::Elf64Types>;
Note: See TracBrowser for help on using the repository browser.