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

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

CLRadeonExtender: Remove obsolete data from AmdCL2BinGen. Change ElfRegion::noteSection definition.
ROCmBinaries: add dynamics and notes.

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