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

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

CLRadeonExtender: Apply Elf notes support in AmdCL2BinGen. write name with zero while storing note in elf (ElfBinGen?).
Add constructors to ElfNote?.

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