source: CLRX/CLRadeonExtender/trunk/CLRX/amdbin/ElfBinaries.h @ 2538

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

CLRadeonExtender: ElfBinaries?. Add routine to create hash table. small fixes in hash routines.

File size: 28.6 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/*! \file ElfBinaries.h
20 * \brief Elf binaries handling
21 */
22
23#ifndef __CLRX_ELFBINARIES_H__
24#define __CLRX_ELFBINARIES_H__
25
26#include <CLRX/Config.h>
27#include <cstddef>
28#include <cstdint>
29#include <climits>
30#include <string>
31#include <utility>
32#include <ostream>
33#include <CLRX/amdbin/Elf.h>
34#include <CLRX/utils/MemAccess.h>
35#include <CLRX/utils/Utilities.h>
36#include <CLRX/utils/Containers.h>
37#include <CLRX/utils/InputOutput.h>
38
39/* INFO: in this file is used ULEV function for conversion
40 * from LittleEndian and unaligned access to other memory access policy and endianness
41 * Please use this function whenever you want to get or set word in ELF binary,
42 * because ELF binaries can be unaligned in memory (as inner binaries).
43 */
44
45/// main namespace
46namespace CLRX
47{
48
49enum: cxuint {
50    BINGEN_DEFAULT = UINT_MAX,    ///< if set in field then field has been filled later
51    BINGEN_NOTSUPPLIED  = UINT_MAX-1 ///< if set in field then field has been ignored
52};
53
54
55enum : Flags {
56    ELF_CREATE_SECTIONMAP = 1,  ///< create map of sections
57    ELF_CREATE_SYMBOLMAP = 2,   ///< create map of symbols
58    ELF_CREATE_DYNSYMMAP = 4,   ///< create map of dynamic symbols
59    ELF_CREATE_ALL = 0xf  ///< creation flags for ELF binaries
60};
61
62/// ELF 32-bit types
63struct Elf32Types
64{
65    typedef uint32_t Size;  ///< size used to return size value
66    typedef uint32_t Word;  ///< word size in ELF
67    typedef uint32_t SectionFlags;  ///< section flags
68    typedef Elf32_Ehdr Ehdr;    ///< ELF header
69    typedef Elf32_Shdr Shdr;    ///< Section header
70    typedef Elf32_Phdr Phdr;    ///< program header
71    typedef Elf32_Sym Sym;      ///< symbol header
72    static const cxbyte ELFCLASS;   ///< ELF class
73    static const cxuint bitness;    ///< ELF bitness
74    static const char* bitName;     ///< bitness name
75    static const Word nobase = Word(0)-1;   ///< address with zero base
76};
77
78/// ELF 32-bit types
79struct Elf64Types
80{
81    typedef size_t Size;  ///< size used to return size value
82    typedef uint64_t Word;  ///< word size in ELF
83    typedef uint64_t SectionFlags;  ///< section flags
84    typedef Elf64_Ehdr Ehdr;    ///< ELF header
85    typedef Elf64_Shdr Shdr;    ///< Section header
86    typedef Elf64_Phdr Phdr;    ///< program header
87    typedef Elf64_Sym Sym;      ///< symbol header
88    static const cxbyte ELFCLASS;   ///< ELF class
89    static const cxuint bitness;    ///< ELF bitness
90    static const char* bitName;     ///< bitness name
91    static const Word nobase = Word(0)-1;   ///< address with zero base
92};
93
94/// ELF binary class
95/** This object doesn't copy binary code content.
96 * Only it takes and uses a binary code.
97 */
98template<typename Types>
99class ElfBinaryTemplate
100{
101public:
102    /// section index map
103    typedef Array<std::pair<const char*, size_t> > SectionIndexMap;
104    /// symbol index map
105    typedef Array<std::pair<const char*, size_t> > SymbolIndexMap;
106protected:
107    Flags creationFlags;   ///< creation flags holder
108    size_t binaryCodeSize;  ///< binary code size
109    cxbyte* binaryCode;       ///< pointer to binary code
110    cxbyte* sectionStringTable;   ///< pointer to section's string table
111    cxbyte* symbolStringTable;    ///< pointer to symbol's string table
112    cxbyte* symbolTable;          ///< pointer to symbol table
113    cxbyte* dynSymStringTable;    ///< pointer to dynamic symbol's string table
114    cxbyte* dynSymTable;          ///< pointer to dynamic symbol table
115    SectionIndexMap sectionIndexMap;    ///< section's index map
116    SymbolIndexMap symbolIndexMap;      ///< symbol's index map
117    SymbolIndexMap dynSymIndexMap;      ///< dynamic symbol's index map
118   
119    typename Types::Size symbolsNum;    ///< symbols number
120    typename Types::Size dynSymbolsNum; ///< dynamic symbols number
121    uint16_t symbolEntSize; ///< symbol entry size in a symbol's table
122    uint16_t dynSymEntSize; ///< dynamic symbol entry size in a dynamic symbol's table
123   
124public:
125    ElfBinaryTemplate();
126    /** constructor.
127     * \param binaryCodeSize binary code size
128     * \param binaryCode pointer to binary code
129     * \param creationFlags flags that specified what will be created during creation
130     */
131    ElfBinaryTemplate(size_t binaryCodeSize, cxbyte* binaryCode,
132                Flags creationFlags = ELF_CREATE_ALL);
133    virtual ~ElfBinaryTemplate();
134   
135    /// get creation flags
136    Flags getCreationFlags() const
137    { return creationFlags; }
138   
139    /// returns true if object has a section's index map
140    bool hasSectionMap() const
141    { return (creationFlags & ELF_CREATE_SECTIONMAP) != 0; }
142   
143    /// returns true if object has a symbol's index map
144    bool hasSymbolMap() const
145    { return (creationFlags & ELF_CREATE_SYMBOLMAP) != 0; }
146   
147    /// returns true if object has a dynamic symbol's index map
148    bool hasDynSymbolMap() const
149    { return (creationFlags & ELF_CREATE_DYNSYMMAP) != 0; }
150   
151    /// get size of binaries
152    size_t getSize() const
153    { return binaryCodeSize; }
154   
155    /// returns true if object is initialized
156    operator bool() const
157    { return binaryCode!=nullptr; }
158   
159    /// returns true if object is uninitialized
160    bool operator!() const
161    { return binaryCode==nullptr; }
162
163    /// get binary code   
164    const cxbyte* getBinaryCode() const
165    { return binaryCode; }
166    /// get binary code
167    cxbyte* getBinaryCode()
168    { return binaryCode; }
169   
170    /// get ELF binary header
171    const typename Types::Ehdr& getHeader() const
172    { return *reinterpret_cast<const typename Types::Ehdr*>(binaryCode); }
173   
174    /// get ELF binary header
175    typename Types::Ehdr& getHeader()
176    { return *reinterpret_cast<typename Types::Ehdr*>(binaryCode); }
177   
178    /// get section headers number
179    uint16_t getSectionHeadersNum() const
180    { return ULEV(getHeader().e_shnum); }
181   
182    /// get section header with specified index
183    const typename Types::Shdr& getSectionHeader(uint16_t index) const
184    {
185        const typename Types::Ehdr& ehdr = getHeader();
186        return *reinterpret_cast<const typename Types::Shdr*>(binaryCode +
187                ULEV(ehdr.e_shoff) + size_t(ULEV(ehdr.e_shentsize))*index);
188    }
189   
190    /// get section header with specified index
191    typename Types::Shdr& getSectionHeader(uint16_t index)
192    {
193        const typename Types::Ehdr& ehdr = getHeader();
194        return *reinterpret_cast<typename Types::Shdr*>(binaryCode +
195                ULEV(ehdr.e_shoff) + size_t(ULEV(ehdr.e_shentsize))*index);
196    }
197   
198    /// get program headers number
199    uint16_t getProgramHeadersNum() const
200    { return ULEV(getHeader().e_phnum); }
201   
202    /// get program header with specified index
203    const typename Types::Phdr& getProgramHeader(uint16_t index) const
204    {
205        const typename Types::Ehdr& ehdr = getHeader();
206        return *reinterpret_cast<const typename Types::Phdr*>(binaryCode +
207                ULEV(ehdr.e_phoff) + size_t(ULEV(ehdr.e_phentsize))*index);
208    }
209   
210    /// get program header with specified index
211    typename Types::Phdr& getProgramHeader(uint16_t index)
212    {
213        const typename Types::Ehdr& ehdr = getHeader();
214        return *reinterpret_cast<typename Types::Phdr*>(binaryCode +
215                ULEV(ehdr.e_phoff) + size_t(ULEV(ehdr.e_phentsize))*index);
216    }
217   
218    /// get symbols number
219    typename Types::Size getSymbolsNum() const
220    { return symbolsNum; }
221   
222    /// get dynamic symbols number
223    typename Types::Size getDynSymbolsNum() const
224    { return dynSymbolsNum; }
225   
226    /// get symbol with specified index
227    const typename Types::Sym& getSymbol(typename Types::Size index) const
228    {
229        return *reinterpret_cast<const typename Types::Sym*>(symbolTable +
230                    size_t(index)*symbolEntSize);
231    }
232   
233    /// get symbol with specified index
234    typename Types::Sym& getSymbol(typename Types::Size index)
235    {
236        return *reinterpret_cast<typename Types::Sym*>(
237            symbolTable + size_t(index)*symbolEntSize);
238    }
239   
240    /// get dynamic symbol with specified index
241    const typename Types::Sym& getDynSymbol(typename Types::Size index) const
242    {
243        return *reinterpret_cast<const typename Types::Sym*>(dynSymTable +
244            size_t(index)*dynSymEntSize);
245    }
246   
247    /// get dynamic symbol with specified index
248    typename Types::Sym& getDynSymbol(typename Types::Size index)
249    {
250        return *reinterpret_cast<typename Types::Sym*>(dynSymTable +
251            size_t(index)*dynSymEntSize);
252    }
253   
254    /// get symbol name with specified index
255    const char* getSymbolName(typename Types::Size index) const
256    {
257        const typename Types::Sym& sym = getSymbol(index);
258        return reinterpret_cast<const char*>(symbolStringTable + ULEV(sym.st_name));
259    }
260   
261    /// get dynamic symbol name with specified index
262    const char* getDynSymbolName(typename Types::Size index) const
263    {
264        const typename Types::Sym& sym = getDynSymbol(index);
265        return reinterpret_cast<const char*>(dynSymStringTable + ULEV(sym.st_name));
266    }
267   
268    /// get section name with specified index
269    const char* getSectionName(uint16_t index) const
270    {
271        const typename Types::Shdr& section = getSectionHeader(index);
272        return reinterpret_cast<const char*>(sectionStringTable + ULEV(section.sh_name));
273    }
274   
275    /// get end iterator if section index map
276    SectionIndexMap::const_iterator getSectionIterEnd() const
277    { return sectionIndexMap.end(); }
278   
279    /// get section iterator with specified name (requires section index map)
280    SectionIndexMap::const_iterator getSectionIter(const char* name) const
281    {
282        SectionIndexMap::const_iterator it = binaryMapFind(
283                    sectionIndexMap.begin(), sectionIndexMap.end(), name, CStringLess());
284        if (it == sectionIndexMap.end())
285            throw Exception(std::string("Can't find Elf")+Types::bitName+" Section");
286        return it;
287    }
288   
289    /// get section index with specified name
290    uint16_t getSectionIndex(const char* name) const;
291   
292    /// get symbol index with specified name (requires symbol index map)
293    typename Types::Size getSymbolIndex(const char* name) const;
294   
295    /// get dynamic symbol index with specified name (requires dynamic symbol index map)
296    typename Types::Size getDynSymbolIndex(const char* name) const;
297   
298    /// get end iterator of symbol index map
299    SymbolIndexMap::const_iterator getSymbolIterEnd() const
300    { return symbolIndexMap.end(); }
301   
302    /// get end iterator of dynamic symbol index map
303    SymbolIndexMap::const_iterator getDynSymbolIterEnd() const
304    { return dynSymIndexMap.end(); }
305   
306    /// get symbol iterator with specified name (requires symbol index map)
307    SymbolIndexMap::const_iterator getSymbolIter(const char* name) const
308    {
309        SymbolIndexMap::const_iterator it = binaryMapFind(
310                    symbolIndexMap.begin(), symbolIndexMap.end(), name, CStringLess());
311        if (it == symbolIndexMap.end())
312            throw Exception(std::string("Can't find Elf")+Types::bitName+" Symbol");
313        return it;
314    }
315
316    /// get dynamic symbol iterator with specified name (requires dynamic symbol index map)
317    SymbolIndexMap::const_iterator getDynSymbolIter(const char* name) const
318    {
319        SymbolIndexMap::const_iterator it = binaryMapFind(
320                    dynSymIndexMap.begin(), dynSymIndexMap.end(), name, CStringLess());
321        if (it == dynSymIndexMap.end())
322            throw Exception(std::string("Can't find Elf")+Types::bitName+" DynSymbol");
323        return it;
324    }
325   
326    /// get section header with specified name
327    const typename Types::Shdr& getSectionHeader(const char* name) const
328    { return getSectionHeader(getSectionIndex(name)); }
329   
330    /// get section header with specified name
331    typename Types::Shdr& getSectionHeader(const char* name)
332    { return getSectionHeader(getSectionIndex(name)); }
333   
334    /// get symbol with specified name (requires symbol index map)
335    const typename Types::Sym& getSymbol(const char* name) const
336    { return getSymbol(getSymbolIndex(name)); }
337   
338    /// get symbol with specified name (requires symbol index map)
339    typename Types::Sym& getSymbol(const char* name)
340    { return getSymbol(getSymbolIndex(name)); }
341   
342    /// get dynamic symbol with specified name (requires dynamic symbol index map)
343    const typename Types::Sym& getDynSymbol(const char* name) const
344    { return getDynSymbol(getDynSymbolIndex(name)); }
345   
346    /// get dynamic symbol with specified name (requires dynamic symbol index map)
347    typename Types::Sym& getDynSymbol(const char* name)
348    { return getDynSymbol(getDynSymbolIndex(name)); }
349   
350    /// get section content pointer
351    const cxbyte* getSectionContent(uint16_t index) const
352    {
353        const typename Types::Shdr& shdr = getSectionHeader(index);
354        return binaryCode + ULEV(shdr.sh_offset);
355    }
356   
357    /// get section content pointer
358    cxbyte* getSectionContent(uint16_t index)
359    {
360        typename Types::Shdr& shdr = getSectionHeader(index);
361        return binaryCode + ULEV(shdr.sh_offset);
362    }
363   
364    /// get section content pointer
365    const cxbyte* getSectionContent(const char* name) const
366    {  return getSectionContent(getSectionIndex(name)); }
367   
368    /// get section content pointer
369    cxbyte* getSectionContent(const char* name)
370    {  return getSectionContent(getSectionIndex(name)); }
371};
372
373extern template class ElfBinaryTemplate<Elf32Types>;
374extern template class ElfBinaryTemplate<Elf64Types>;
375
376/// check whether binary data is is ELF binary
377extern bool isElfBinary(size_t binarySize, const cxbyte* binary);
378
379/// type for 32-bit ELF binary
380typedef class ElfBinaryTemplate<Elf32Types> ElfBinary32;
381/// type for 64-bit ELF binary
382typedef class ElfBinaryTemplate<Elf64Types> ElfBinary64;
383
384/// type of Elf region
385enum class ElfRegionType: cxbyte
386{
387    PHDR_TABLE, ///< program header table
388    SHDR_TABLE, ///< section header table
389    SECTION,    ///< section
390    USER        ///< user region
391};
392
393/// elf region content generator for elf region
394class ElfRegionContent
395{
396public:
397    virtual ~ElfRegionContent();
398   
399    /// operator that generates content
400    virtual void operator()(FastOutputBuffer& fob) const = 0;
401};
402
403/// elf header template
404template<typename Types>
405struct ElfHeaderTemplate
406{
407    typename Types::Word paddrBase; ///< physical address base
408    typename Types::Word vaddrBase; ///< virtual address base
409    cxbyte osABI;   ///< os abi
410    cxbyte abiVersion;  ///< ABI version
411    uint16_t type;  ///< type
412    uint16_t machine;   ///< machine
413    uint32_t version;   ///< version
414    cxuint entryRegion; ///< region in which is entry
415    typename Types::Word entry; ///< entry offset relative to region
416    uint32_t flags; ///< flags
417};
418
419/// 32-bit elf header
420typedef ElfHeaderTemplate<Elf32Types> ElfHeader32;
421/// 64-bit elf header
422typedef ElfHeaderTemplate<Elf64Types> ElfHeader64;
423
424
425enum: cxuint {
426    ELFSECTID_START = UINT_MAX-255,
427    ELFSECTID_SHSTRTAB = ELFSECTID_START,
428    ELFSECTID_STRTAB,
429    ELFSECTID_SYMTAB,
430    ELFSECTID_DYNSTR,
431    ELFSECTID_DYNSYM,
432    ELFSECTID_TEXT,
433    ELFSECTID_RODATA,
434    ELFSECTID_DATA,
435    ELFSECTID_BSS,
436    ELFSECTID_COMMENT,
437    ELFSECTID_STD_MAX = ELFSECTID_COMMENT,
438    ELFSECTID_OTHER_BUILTIN = ELFSECTID_STD_MAX+1,
439    ELFSECTID_NULL = UINT_MAX-2,
440    ELFSECTID_ABS = UINT_MAX-1,
441    ELFSECTID_UNDEF = UINT_MAX
442};
443
444/// section structure to external usage (for example in the binary generator input)
445struct BinSection
446{
447    CString name;   ///< name of section
448    size_t size;    ///< size of content
449    const cxbyte* data; ///< data content
450    uint64_t align;  ///< region alignment
451    uint32_t type;  ///< section type
452    uint64_t flags; ///< section flags
453    cxuint linkId; ///< link section id (ELFSECTID_* or an extra section index)
454    uint32_t info;  ///< section info
455    size_t entSize;    ///< entries size
456};
457
458/// symbol structure to external usage (fo example in the binary generator input)
459struct BinSymbol
460{
461    CString name;   ///< name
462    uint64_t value;  ///< symbol value
463    uint64_t size;   ///< symbol size
464    cxuint sectionId; ///< section id (ELFSECTID_* or an extra section index)
465    bool valueIsAddr;   ///< true if value should be treats as address
466    cxbyte info;    ///< info
467    cxbyte other;   ///< other
468};
469
470/// convert section id to elf section id
471extern uint16_t convertSectionId(cxuint sectionIndex, const uint16_t* builtinSections,
472                  cxuint maxBuiltinSection, cxuint extraSectionIndex);
473
474/// template of ElfRegion
475template<typename Types>
476struct ElfRegionTemplate
477{
478    ElfRegionType type; ///< type of region
479   
480    /// true if content from pointer, otherwise will be generated from class
481    bool dataFromPointer;
482   
483    /// region size
484    /** if alignment of this region is zero and size doesn't to alignment of next region
485     * then size of this region will be fixed to alignment of next region */
486    typename Types::Word size;
487    typename Types::Word align;  ///< region alignment
488    union
489    {
490        const cxbyte* data; ///< content from pointer
491        const ElfRegionContent* dataGen;    ///< content generator pointer
492    };
493    struct {
494        const char* name;   ///< section name
495        uint32_t type;  ///< section type
496        typename Types::SectionFlags flags; ///< section flags
497        uint32_t link;  ///< section link
498        uint32_t info;  ///< section info
499        typename Types::Word addrBase;   ///< section address base
500        typename Types::Word entSize;    ///< entries size
501        bool zeroOffset;
502        typename Types::Word align;
503    } section;  ///< section structure
504   
505    /// constructor for user region
506    ElfRegionTemplate(typename Types::Word _size,
507              const cxbyte* _data, typename Types::Word _align)
508            : type(ElfRegionType::USER), dataFromPointer(true), size(_size),
509              align(_align), data(_data)
510    { }
511   
512    /// constructor for user region with content generator
513    ElfRegionTemplate(typename Types::Word _size,
514              const ElfRegionContent* contentGen, typename Types::Word _align)
515            : type(ElfRegionType::USER), dataFromPointer(false), size(_size),
516              align(_align), dataGen(contentGen)
517    { }
518   
519    /// constructor for region
520    ElfRegionTemplate(ElfRegionType _type, typename Types::Word _size,
521              const cxbyte* _data, typename Types::Word _align)
522            : type(_type), dataFromPointer(true), size(_size),
523              align(_align), data(_data)
524    { }
525   
526    /// constructor for region with content generator
527    ElfRegionTemplate(ElfRegionType _type, typename Types::Word _size,
528              const ElfRegionContent* contentGen, typename Types::Word _align)
529            : type(_type), dataFromPointer(false), size(_size),
530              align(_align), dataGen(contentGen)
531    { }
532   
533    /// constructor for section
534    ElfRegionTemplate(typename Types::Word _size, const cxbyte* _data,
535              typename Types::Word _align, const char* _name, uint32_t _type,
536              typename Types::SectionFlags _flags, uint32_t _link = 0, uint32_t _info = 0,
537              typename Types::Word _addrBase = 0,
538              typename Types::Word _entSize = 0, bool _zeroOffset = false,
539              typename Types::Word _sectAlign = 0)
540            : type(ElfRegionType::SECTION), dataFromPointer(true), size(_size),
541              align(_align), data(_data)
542    {
543        section = {_name, _type, _flags, _link, _info, _addrBase,
544            _entSize, _zeroOffset, _sectAlign};
545    }
546   
547    /// constructor for section with generator
548    ElfRegionTemplate(typename Types::Word _size, const ElfRegionContent* _data,
549              typename Types::Word _align, const char* inName, uint32_t _type,
550              typename Types::SectionFlags _flags, uint32_t _link = 0, uint32_t _info = 0,
551              typename Types::Word _addrBase = 0,
552              typename Types::Word _entSize = 0, bool _zeroOffset = false,
553              typename Types::Word _sectAlign = 0)
554            : type(ElfRegionType::SECTION), dataFromPointer(false), size(_size),
555              align(_align), dataGen(_data)
556    {
557        section = {inName, _type, _flags, _link, _info, _addrBase,
558            _entSize, _zeroOffset, _sectAlign};
559    }
560    /// constructor for external section (BinSection)
561    /**
562     * \param binSection external section
563     * \param builtinSections ELF section indices for builtin sections
564     * \param maxBuiltinSection maximal id of builtin section (as ELFSECTID_STD_MAX)
565     * \param startExtraIndex first ELF section id for extra section
566     */
567    ElfRegionTemplate(const BinSection& binSection, const uint16_t* builtinSections,
568                  cxuint maxBuiltinSection, cxuint startExtraIndex)
569            : type(ElfRegionType::SECTION), dataFromPointer(true), size(binSection.size),
570              align(binSection.align), data(binSection.data)
571    {
572        section = { binSection.name.c_str(), binSection.type, 
573            typename Types::SectionFlags(binSection.flags),
574            uint32_t(convertSectionId(binSection.linkId, builtinSections,
575                             maxBuiltinSection, startExtraIndex)),
576            binSection.info, 0, typename Types::Word(binSection.entSize), 0 };
577    }
578   
579    /// get program header table region
580    static ElfRegionTemplate programHeaderTable()
581    { return ElfRegionTemplate(ElfRegionType::PHDR_TABLE, 0, (const cxbyte*)nullptr,
582               sizeof(typename Types::Word)); }
583   
584    /// get program header table region
585    static ElfRegionTemplate sectionHeaderTable()
586    { return ElfRegionTemplate(ElfRegionType::SHDR_TABLE, 0, (const cxbyte*)nullptr,
587                sizeof(typename Types::Word)); }
588   
589    /// get .strtab section
590    static ElfRegionTemplate strtabSection()
591    { return ElfRegionTemplate(0, (const cxbyte*)nullptr, 1, ".strtab", SHT_STRTAB, 0); }
592   
593    /// get .dynstr section
594    static ElfRegionTemplate dynstrSection()
595    { return ElfRegionTemplate(0, (const cxbyte*)nullptr, 1, ".dynstr", SHT_STRTAB,
596                SHF_ALLOC); }
597   
598    /// get .shstrtab section
599    static ElfRegionTemplate shstrtabSection()
600    { return ElfRegionTemplate(0, (const cxbyte*)nullptr, 1, ".shstrtab", SHT_STRTAB, 0); }
601   
602    /// get symtab section
603    static ElfRegionTemplate symtabSection()
604    { return ElfRegionTemplate(0, (const cxbyte*)nullptr, sizeof(typename Types::Word),
605                ".symtab", SHT_SYMTAB, 0); }
606   
607    /// get dynsym section
608    static ElfRegionTemplate dynsymSection()
609    { return ElfRegionTemplate(0, (const cxbyte*)nullptr, sizeof(typename Types::Word),
610                ".dynsym", SHT_DYNSYM, SHF_ALLOC); }
611   
612    /// get hash section
613    static ElfRegionTemplate hashSection(uint16_t link)
614    { return ElfRegionTemplate(0, (const cxbyte*)nullptr, sizeof(typename Types::Word),
615                ".hash", SHT_HASH, SHF_ALLOC, link); }
616};
617
618/// 32-bit region (for 32-bit elf)
619typedef ElfRegionTemplate<Elf32Types> ElfRegion32;
620/// 64-bit region (for 64-bit elf)
621typedef ElfRegionTemplate<Elf64Types> ElfRegion64;
622
623/// template of ELF program header
624template<typename Types>
625struct ElfProgramHeaderTemplate
626{
627    uint32_t type;  ///< type
628    uint32_t flags; ///< flags
629    cxuint regionStart; ///< number of first region which is in program header data
630    cxuint regionsNum;  ///< number of regions whose is in program header data
631    bool haveMemSize;   ///< true if program header has memory size
632    typename Types::Word paddrBase;  ///< paddr base
633    typename Types::Word vaddrBase;  ///< vaddr base
634    typename Types::Word memSize;    ///< size in memory
635};
636
637/// 32-bit elf program header
638typedef ElfProgramHeaderTemplate<Elf32Types> ElfProgramHeader32;
639/// 64-bit elf program header
640typedef ElfProgramHeaderTemplate<Elf64Types> ElfProgramHeader64;
641
642/// ELF symbol template
643template<typename Types>
644struct ElfSymbolTemplate
645{
646    const char* name;   ///< name
647    uint16_t sectionIndex;  ///< section index for which symbol is
648    cxbyte info;    ///< info
649    cxbyte other;   ///< other
650    bool valueIsAddr;   ///< true if value should be treats as address
651    typename Types::Word value;  ///< symbol value
652    typename Types::Word size;   ///< symbol size
653   
654    /// constructor (to replace initializer list construction)
655    ElfSymbolTemplate(const char* _name, uint16_t _sectionIndex,
656                cxbyte _info, cxbyte _other, bool _valueIsAddr,
657                typename Types::Word _value, typename Types::Word _size)
658        : name(_name), sectionIndex(_sectionIndex), info(_info), other(_other),
659          valueIsAddr(_valueIsAddr), value(_value), size(_size)
660    { }
661    /// constructor for extra symbol
662    /**
663     * \param binSymbol external symbol
664     * \param builtinSections ELF section indices for builtin sections
665     * \param maxBuiltinSection maximal id of builtin section (as ELFSECTID_STD_MAX)
666     * \param startExtraIndex first ELF section id for extra section
667     */
668    ElfSymbolTemplate(const BinSymbol& binSymbol, const uint16_t* builtinSections,
669                  cxuint maxBuiltinSection, cxuint startExtraIndex)
670    {
671        name = binSymbol.name.c_str();
672        sectionIndex = convertSectionId(binSymbol.sectionId, builtinSections,
673                    maxBuiltinSection, startExtraIndex);
674        info = binSymbol.info;
675        other = binSymbol.other;
676        valueIsAddr = binSymbol.valueIsAddr;
677        value = binSymbol.value;
678        size = binSymbol.size;
679    }
680};
681
682/// 32-bit elf symbol
683typedef ElfSymbolTemplate<Elf32Types> ElfSymbol32;
684/// 64-bit elf symbol
685typedef ElfSymbolTemplate<Elf64Types> ElfSymbol64;
686
687/// ELF binary generator
688template<typename Types>
689class ElfBinaryGenTemplate
690{
691private:
692    bool sizeComputed;
693    bool addNullSym, addNullDynSym;
694    bool addNullSection;
695    cxuint addrStartRegion;
696    uint16_t shStrTab, strTab, dynStr;
697    cxuint shdrTabRegion, phdrTabRegion;
698    uint16_t sectionsNum;
699    typename Types::Word size;
700    ElfHeaderTemplate<Types> header;
701    std::vector<ElfRegionTemplate<Types> > regions;
702    std::unique_ptr<typename Types::Word[]> regionOffsets;
703    std::unique_ptr<typename Types::Word[]> regionAddresses;
704    std::unique_ptr<cxuint[]> sectionRegions;
705    std::vector<ElfProgramHeaderTemplate<Types> > progHeaders;
706    std::vector<ElfSymbolTemplate<Types> > symbols;
707    std::vector<ElfSymbolTemplate<Types> > dynSymbols;
708   
709    void computeSize();
710public:
711    ElfBinaryGenTemplate();
712    /// construcrtor
713    /**
714     * \param header elf header template
715     * \param addNullSym if true then add null symbol to symbol table
716     * \param addNullDynSym if true then add null dynsymbol to dynsymbol table
717     * \param addNullSection if true then add null section to section table
718     * \param addrCountingFromRegion begins counting address from region with that index
719     */
720    explicit ElfBinaryGenTemplate(const ElfHeaderTemplate<Types>& header,
721            bool addNullSym = true, bool addNullDynSym = true,
722            bool addNullSection = true, cxuint addrCountingFromRegion = 0);
723   
724    /// set elf header
725    void setHeader(const ElfHeaderTemplate<Types>& header)
726    { this->header = header; }
727   
728    /// add new region (section, user region or shdr/phdr table
729    void addRegion(const ElfRegionTemplate<Types>& region);
730    /// add new program header
731    void addProgramHeader(const ElfProgramHeaderTemplate<Types>& progHeader);
732   
733    /// add symbol
734    void addSymbol(const ElfSymbolTemplate<Types>& symbol)
735    { symbols.push_back(symbol); }
736    /// add dynamic symbol
737    void addDynSymbol(const ElfSymbolTemplate<Types>& symbol)
738    { dynSymbols.push_back(symbol); }
739   
740    /// count size of binary
741    uint64_t countSize();
742   
743    /// generate binary
744    void generate(FastOutputBuffer& fob);
745   
746    /// generate binary
747    void generate(std::ostream& os)
748    {
749        FastOutputBuffer fob(256, os);
750        generate(fob);
751    }
752};
753
754extern template class ElfBinaryGenTemplate<Elf32Types>;
755extern template class ElfBinaryGenTemplate<Elf64Types>;
756
757/// type for 32-bit ELF binary generator
758typedef class ElfBinaryGenTemplate<Elf32Types> ElfBinaryGen32;
759/// type for 64-bit ELF binary generator
760typedef class ElfBinaryGenTemplate<Elf64Types> ElfBinaryGen64;
761
762};
763
764#endif
Note: See TracBrowser for help on using the repository browser.