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

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

CLRadeonExtender: Add BINGEN64_XXXX enums (for 64-bit values).

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