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

Last change on this file since 3761 was 3761, checked in by matszpk, 19 months ago

CLRadeonExtender: Asm: Preliminaries to section differences in expressions.

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