source: CLRX/CLRadeonExtender/trunk/amdbin/ROCmBinaries.cpp @ 3671

Last change on this file since 3671 was 3671, checked in by matszpk, 23 months ago

CLRadeonExtender: AsmROCm: Add '.tripple' to set same LLVM target tripple without device name.
CLRXDocs: add '.tripple' and '.target' descriptions.

File size: 21.5 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
20#include <CLRX/Config.h>
21#include <cassert>
22#include <cstdio>
23#include <cstdint>
24#include <algorithm>
25#include <utility>
26#include <CLRX/amdbin/ElfBinaries.h>
27#include <CLRX/utils/Utilities.h>
28#include <CLRX/utils/MemAccess.h>
29#include <CLRX/utils/InputOutput.h>
30#include <CLRX/utils/Containers.h>
31#include <CLRX/amdbin/ROCmBinaries.h>
32
33using namespace CLRX;
34
35/* TODO: add support for various kernel code offset (now only 256 is supported) */
36
37ROCmBinary::ROCmBinary(size_t binaryCodeSize, cxbyte* binaryCode, Flags creationFlags)
38        : ElfBinary64(binaryCodeSize, binaryCode, creationFlags),
39          regionsNum(0), codeSize(0), code(nullptr),
40          globalDataSize(0), globalData(nullptr), metadataSize(0), metadata(nullptr),
41          newBinFormat(false)
42{
43    cxuint textIndex = SHN_UNDEF;
44    try
45    { textIndex = getSectionIndex(".text"); }
46    catch(const Exception& ex)
47    { } // ignore failed
48    uint64_t codeOffset = 0;
49    // find '.text' section
50    if (textIndex!=SHN_UNDEF)
51    {
52        code = getSectionContent(textIndex);
53        const Elf64_Shdr& textShdr = getSectionHeader(textIndex);
54        codeSize = ULEV(textShdr.sh_size);
55        codeOffset = ULEV(textShdr.sh_offset);
56    }
57   
58    cxuint rodataIndex = SHN_UNDEF;
59    try
60    { rodataIndex = getSectionIndex(".rodata"); }
61    catch(const Exception& ex)
62    { } // ignore failed
63    // find '.text' section
64    if (rodataIndex!=SHN_UNDEF)
65    {
66        globalData = getSectionContent(rodataIndex);
67        const Elf64_Shdr& rodataShdr = getSectionHeader(rodataIndex);
68        globalDataSize = ULEV(rodataShdr.sh_size);
69    }
70   
71    cxuint gpuConfigIndex = SHN_UNDEF;
72    try
73    { gpuConfigIndex = getSectionIndex(".AMDGPU.config"); }
74    catch(const Exception& ex)
75    { } // ignore failed
76    newBinFormat = (gpuConfigIndex == SHN_UNDEF);
77   
78    // counts regions (symbol or kernel)
79    regionsNum = 0;
80    const size_t symbolsNum = getSymbolsNum();
81    for (size_t i = 0; i < symbolsNum; i++)
82    {
83        // count regions number
84        const Elf64_Sym& sym = getSymbol(i);
85        const cxbyte symType = ELF64_ST_TYPE(sym.st_info);
86        const cxbyte bind = ELF64_ST_BIND(sym.st_info);
87        if (ULEV(sym.st_shndx)==textIndex &&
88            (symType==STT_GNU_IFUNC || symType==STT_FUNC ||
89                (bind==STB_GLOBAL && symType==STT_OBJECT)))
90            regionsNum++;
91    }
92    if (code==nullptr && regionsNum!=0)
93        throw BinException("No code if regions number is not zero");
94    regions.reset(new ROCmRegion[regionsNum]);
95    size_t j = 0;
96    typedef std::pair<uint64_t, size_t> RegionOffsetEntry;
97    std::unique_ptr<RegionOffsetEntry[]> symOffsets(new RegionOffsetEntry[regionsNum]);
98   
99    // get regions info
100    for (size_t i = 0; i < symbolsNum; i++)
101    {
102        const Elf64_Sym& sym = getSymbol(i);
103        if (ULEV(sym.st_shndx)!=textIndex)
104            continue;   // if not in '.text' section
105        const size_t value = ULEV(sym.st_value);
106        if (value < codeOffset)
107            throw BinException("Region offset is too small!");
108        const size_t size = ULEV(sym.st_size);
109       
110        const cxbyte symType = ELF64_ST_TYPE(sym.st_info);
111        const cxbyte bind = ELF64_ST_BIND(sym.st_info);
112        if (symType==STT_GNU_IFUNC || symType==STT_FUNC ||
113                (bind==STB_GLOBAL && symType==STT_OBJECT))
114        {
115            ROCmRegionType type = ROCmRegionType::DATA;
116            // if kernel
117            if (symType==STT_GNU_IFUNC) 
118                type = ROCmRegionType::KERNEL;
119            // if function kernel
120            else if (symType==STT_FUNC)
121                type = ROCmRegionType::FKERNEL;
122            symOffsets[j] = std::make_pair(value, j);
123            if (type!=ROCmRegionType::DATA && value+0x100 > codeOffset+codeSize)
124                throw BinException("Kernel or code offset is too big!");
125            regions[j++] = { getSymbolName(i), size, value, type };
126        }
127    }
128    // sort regions by offset
129    std::sort(symOffsets.get(), symOffsets.get()+regionsNum,
130            [](const RegionOffsetEntry& a, const RegionOffsetEntry& b)
131            { return a.first < b.first; });
132    // checking distance between regions
133    for (size_t i = 1; i <= regionsNum; i++)
134    {
135        size_t end = (i<regionsNum) ? symOffsets[i].first : codeOffset+codeSize;
136        ROCmRegion& region = regions[symOffsets[i-1].second];
137        if (region.type==ROCmRegionType::KERNEL && symOffsets[i-1].first+0x100 > end)
138            throw BinException("Kernel size is too small!");
139       
140        const size_t regSize = end - symOffsets[i-1].first;
141        if (region.size==0)
142            region.size = regSize;
143        else
144            region.size = std::min(regSize, region.size);
145    }
146   
147    // get metadata
148    const size_t notesSize = getNotesSize();
149    const cxbyte* noteContent = (const cxbyte*)getNotes();
150   
151    for (size_t offset = 0; offset < notesSize; )
152    {
153        const Elf64_Nhdr* nhdr = (const Elf64_Nhdr*)(noteContent + offset);
154        size_t namesz = ULEV(nhdr->n_namesz);
155        size_t descsz = ULEV(nhdr->n_descsz);
156        if (usumGt(offset, namesz+descsz, notesSize))
157            throw BinException("Note offset+size out of range");
158       
159        if (namesz==4 &&
160            ::strcmp((const char*)noteContent+offset+ sizeof(Elf64_Nhdr), "AMD")==0)
161        {
162            const uint32_t noteType = ULEV(nhdr->n_type);
163            if (noteType == 0xa)
164            {
165                metadata = (char*)(noteContent+offset+sizeof(Elf64_Nhdr) + 4);
166                metadataSize = descsz;
167            }
168            else if (noteType == 0xb)
169                target.assign((char*)(noteContent+offset+sizeof(Elf64_Nhdr) + 4), descsz);
170        }
171        size_t align = (((namesz+descsz)&3)!=0) ? 4-((namesz+descsz)&3) : 0;
172        offset += sizeof(Elf64_Nhdr) + namesz + descsz + align;
173    }
174   
175    if (hasRegionMap())
176    {
177        // create region map
178        regionsMap.resize(regionsNum);
179        for (size_t i = 0; i < regionsNum; i++)
180            regionsMap[i] = std::make_pair(regions[i].regionName, i);
181        // sort region map
182        mapSort(regionsMap.begin(), regionsMap.end());
183    }
184}
185
186/// determint GPU device from ROCm notes
187GPUDeviceType ROCmBinary::determineGPUDeviceType(uint32_t& outArchMinor,
188                     uint32_t& outArchStepping) const
189{
190    uint32_t archMajor = 0;
191    uint32_t archMinor = 0;
192    uint32_t archStepping = 0;
193   
194    {
195        const cxbyte* noteContent = (const cxbyte*)getNotes();
196        if (noteContent==nullptr)
197            throw BinException("Missing notes in inner binary!");
198        size_t notesSize = getNotesSize();
199        // find note about AMDGPU
200        for (size_t offset = 0; offset < notesSize; )
201        {
202            const Elf64_Nhdr* nhdr = (const Elf64_Nhdr*)(noteContent + offset);
203            size_t namesz = ULEV(nhdr->n_namesz);
204            size_t descsz = ULEV(nhdr->n_descsz);
205            if (usumGt(offset, namesz+descsz, notesSize))
206                throw BinException("Note offset+size out of range");
207            if (ULEV(nhdr->n_type) == 0x3 && namesz==4 && descsz>=0x1a &&
208                ::strcmp((const char*)noteContent+offset+sizeof(Elf64_Nhdr), "AMD")==0)
209            {    // AMDGPU type
210                const uint32_t* content = (const uint32_t*)
211                        (noteContent+offset+sizeof(Elf64_Nhdr) + 4);
212                archMajor = ULEV(content[1]);
213                archMinor = ULEV(content[2]);
214                archStepping = ULEV(content[3]);
215            }
216            size_t align = (((namesz+descsz)&3)!=0) ? 4-((namesz+descsz)&3) : 0;
217            offset += sizeof(Elf64_Nhdr) + namesz + descsz + align;
218        }
219    }
220    // determine device type
221    GPUDeviceType deviceType = getGPUDeviceTypeFromArchVersion(archMajor, archMinor,
222                                    archStepping);
223    outArchMinor = archMinor;
224    outArchStepping = archStepping;
225    return deviceType;
226}
227
228const ROCmRegion& ROCmBinary::getRegion(const char* name) const
229{
230    RegionMap::const_iterator it = binaryMapFind(regionsMap.begin(),
231                             regionsMap.end(), name);
232    if (it == regionsMap.end())
233        throw BinException("Can't find region name");
234    return regions[it->second];
235}
236
237// if ROCm binary
238bool CLRX::isROCmBinary(size_t binarySize, const cxbyte* binary)
239{
240    if (!isElfBinary(binarySize, binary))
241        return false;
242    if (binary[EI_CLASS] != ELFCLASS64)
243        return false;
244    const Elf64_Ehdr* ehdr = reinterpret_cast<const Elf64_Ehdr*>(binary);
245    if (ULEV(ehdr->e_machine) != 0xe0)
246        return false;
247    return true;
248}
249
250
251void ROCmInput::addEmptyKernel(const char* kernelName)
252{
253    symbols.push_back({ kernelName, 0, 0, ROCmRegionType::KERNEL });
254}
255
256/*
257 * ROCm Binary Generator
258 */
259
260ROCmBinGenerator::ROCmBinGenerator() : manageable(false), input(nullptr)
261{ }
262
263ROCmBinGenerator::ROCmBinGenerator(const ROCmInput* rocmInput)
264        : manageable(false), input(rocmInput)
265{ }
266
267ROCmBinGenerator::ROCmBinGenerator(GPUDeviceType deviceType,
268        uint32_t archMinor, uint32_t archStepping, size_t codeSize, const cxbyte* code,
269        size_t globalDataSize, const cxbyte* globalData,
270        const std::vector<ROCmSymbolInput>& symbols)
271{
272    input = new ROCmInput{ deviceType, archMinor, archStepping, 0, false,
273            globalDataSize, globalData, symbols, codeSize, code };
274}
275
276ROCmBinGenerator::ROCmBinGenerator(GPUDeviceType deviceType,
277        uint32_t archMinor, uint32_t archStepping, size_t codeSize, const cxbyte* code,
278        size_t globalDataSize, const cxbyte* globalData,
279        std::vector<ROCmSymbolInput>&& symbols)
280{
281    input = new ROCmInput{ deviceType, archMinor, archStepping, 0, false,
282            globalDataSize, globalData, std::move(symbols), codeSize, code };
283}
284
285ROCmBinGenerator::~ROCmBinGenerator()
286{
287    if (manageable)
288        delete input;
289}
290
291void ROCmBinGenerator::setInput(const ROCmInput* input)
292{
293    if (manageable)
294        delete input;
295    manageable = false;
296    this->input = input;
297}
298
299// ELF notes contents
300static const cxbyte noteDescType1[8] =
301{ 2, 0, 0, 0, 1, 0, 0, 0 };
302
303static const cxbyte noteDescType3[27] =
304{ 4, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
305  'A', 'M', 'D', 0, 'A', 'M', 'D', 'G', 'P', 'U', 0 };
306
307static inline void addMainSectionToTable(cxuint& sectionsNum, uint16_t* builtinTable,
308                cxuint elfSectId)
309{ builtinTable[elfSectId - ELFSECTID_START] = sectionsNum++; }
310
311void ROCmBinGenerator::generateInternal(std::ostream* osPtr, std::vector<char>* vPtr,
312             Array<cxbyte>* aPtr) const
313{
314    AMDGPUArchVersion amdGpuArchValues = getGPUArchVersion(input->deviceType,
315                GPUArchVersionTable::OPENSOURCE);
316    if (input->archMinor!=UINT32_MAX)
317        amdGpuArchValues.minor = input->archMinor;
318    if (input->archStepping!=UINT32_MAX)
319        amdGpuArchValues.stepping = input->archStepping;
320   
321    const char* comment = "CLRX ROCmBinGenerator " CLRX_VERSION;
322    uint32_t commentSize = ::strlen(comment);
323    if (input->comment!=nullptr)
324    {
325        // if comment, store comment section
326        comment = input->comment;
327        commentSize = input->commentSize;
328        if (commentSize==0)
329            commentSize = ::strlen(comment);
330    }
331   
332    uint32_t eflags = input->newBinFormat ? 2 : 0;
333    if (input->eflags != BINGEN_DEFAULT)
334        eflags = input->eflags;
335   
336    ElfBinaryGen64 elfBinGen64({ 0U, 0U, 0x40, 0, ET_DYN,
337            0xe0, EV_CURRENT, UINT_MAX, 0, eflags },
338            true, true, true, PHREGION_FILESTART);
339   
340    uint16_t mainBuiltinSectTable[ROCMSECTID_MAX-ELFSECTID_START+1];
341    std::fill(mainBuiltinSectTable,
342              mainBuiltinSectTable + ROCMSECTID_MAX-ELFSECTID_START+1, SHN_UNDEF);
343    cxuint mainSectionsNum = 1;
344   
345    // generate main builtin section table (for section id translation)
346    if (input->newBinFormat)
347        addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ROCMSECTID_NOTE);
348    if (input->globalData != nullptr)
349        addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ELFSECTID_RODATA);
350    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ELFSECTID_DYNSYM);
351    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ROCMSECTID_HASH);
352    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ELFSECTID_DYNSTR);
353    const cxuint execProgHeaderRegionIndex = mainSectionsNum;
354    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ELFSECTID_TEXT);
355    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ROCMSECTID_DYNAMIC);
356    if (!input->newBinFormat)
357    {
358        addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ROCMSECTID_NOTE);
359        addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ROCMSECTID_GPUCONFIG);
360    }
361    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ELFSECTID_COMMENT);
362    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ELFSECTID_SYMTAB);
363    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ELFSECTID_SHSTRTAB);
364    addMainSectionToTable(mainSectionsNum, mainBuiltinSectTable, ELFSECTID_STRTAB);
365   
366    // add symbols (kernels, function kernels and data symbols)
367    elfBinGen64.addSymbol(ElfSymbol64("_DYNAMIC",
368                  mainBuiltinSectTable[ROCMSECTID_DYNAMIC-ELFSECTID_START],
369                  ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE), STV_HIDDEN, true, 0, 0));
370    const uint16_t textSectIndex = mainBuiltinSectTable[ELFSECTID_TEXT-ELFSECTID_START];
371    for (const ROCmSymbolInput& symbol: input->symbols)
372    {
373        ElfSymbol64 elfsym;
374        switch (symbol.type)
375        {
376            case ROCmRegionType::KERNEL:
377                elfsym = ElfSymbol64(symbol.symbolName.c_str(), textSectIndex,
378                      ELF64_ST_INFO(STB_GLOBAL, STT_GNU_IFUNC), 0, true,
379                      symbol.offset, symbol.size);
380                break;
381            case ROCmRegionType::FKERNEL:
382                elfsym = ElfSymbol64(symbol.symbolName.c_str(), textSectIndex,
383                      ELF64_ST_INFO(STB_GLOBAL, STT_FUNC), 0, true,
384                      symbol.offset, symbol.size);
385                break;
386            case ROCmRegionType::DATA:
387                elfsym = ElfSymbol64(symbol.symbolName.c_str(), textSectIndex,
388                      ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT), 0, true,
389                      symbol.offset, symbol.size);
390                break;
391            default:
392                break;
393        }
394        // add to symbols and dynamic symbols table
395        elfBinGen64.addSymbol(elfsym);
396        elfBinGen64.addDynSymbol(elfsym);
397    }
398   
399    static const int32_t dynTags[] = {
400        DT_SYMTAB, DT_SYMENT, DT_STRTAB, DT_STRSZ, DT_HASH };
401    elfBinGen64.addDynamics(sizeof(dynTags)/sizeof(int32_t), dynTags);
402   
403    // elf program headers
404    elfBinGen64.addProgramHeader({ PT_PHDR, PF_R, 0, 1,
405                    true, Elf64Types::nobase, Elf64Types::nobase, 0 });
406    elfBinGen64.addProgramHeader({ PT_LOAD, PF_R, PHREGION_FILESTART,
407                    execProgHeaderRegionIndex,
408                    true, Elf64Types::nobase, Elf64Types::nobase, 0, 0x1000 });
409    elfBinGen64.addProgramHeader({ PT_LOAD, PF_R|PF_X, execProgHeaderRegionIndex, 1,
410                    true, Elf64Types::nobase, Elf64Types::nobase, 0 });
411    elfBinGen64.addProgramHeader({ PT_LOAD, PF_R|PF_W, execProgHeaderRegionIndex+1, 1,
412                    true, Elf64Types::nobase, Elf64Types::nobase, 0 });
413    elfBinGen64.addProgramHeader({ PT_DYNAMIC, PF_R|PF_W, execProgHeaderRegionIndex+1, 1,
414                    true, Elf64Types::nobase, Elf64Types::nobase, 0, 8 });
415    elfBinGen64.addProgramHeader({ PT_GNU_RELRO, PF_R, execProgHeaderRegionIndex+1, 1,
416                    true, Elf64Types::nobase, Elf64Types::nobase, 0, 1 });
417    elfBinGen64.addProgramHeader({ PT_GNU_STACK, PF_R|PF_W, PHREGION_FILESTART, 0,
418                    true, 0, 0, 0 });
419   
420    if (input->newBinFormat)
421        // program header for note (new binary format)
422        elfBinGen64.addProgramHeader({ PT_NOTE, PF_R, 1, 1, true,
423                    Elf64Types::nobase, Elf64Types::nobase, 0, 4 });
424   
425    std::string target = input->target.c_str();
426    if (target.empty() && !input->targetTripple.empty())
427    {
428        target = input->targetTripple.c_str();
429        char dbuf[20];
430        snprintf(dbuf, 20, "-gfx%u%u%u", amdGpuArchValues.major, amdGpuArchValues.minor,
431                 amdGpuArchValues.stepping);
432        target += dbuf;
433    }
434    // elf notes
435    elfBinGen64.addNote({"AMD", sizeof noteDescType1, noteDescType1, 1U});
436    std::unique_ptr<cxbyte[]> noteBuf(new cxbyte[0x1b]);
437    ::memcpy(noteBuf.get(), noteDescType3, 0x1b);
438    SULEV(*(uint32_t*)(noteBuf.get()+4), amdGpuArchValues.major);
439    SULEV(*(uint32_t*)(noteBuf.get()+8), amdGpuArchValues.minor);
440    SULEV(*(uint32_t*)(noteBuf.get()+12), amdGpuArchValues.stepping);
441    elfBinGen64.addNote({"AMD", 0x1b, noteBuf.get(), 3U});
442    if (!target.empty())
443        elfBinGen64.addNote({"AMD", target.size(), (const cxbyte*)target.c_str(), 0xbU});
444    if (input->metadataSize != 0)
445        elfBinGen64.addNote({"AMD", input->metadataSize,
446                (const cxbyte*)input->metadata, 0xaU});
447   
448    /// region and sections
449    elfBinGen64.addRegion(ElfRegion64::programHeaderTable());
450    if (input->newBinFormat)
451        elfBinGen64.addRegion(ElfRegion64::noteSection());
452    if (input->globalData != nullptr)
453        elfBinGen64.addRegion(ElfRegion64(input->globalDataSize, input->globalData, 4,
454                ".rodata", SHT_PROGBITS, SHF_ALLOC, 0, 0, Elf64Types::nobase));
455   
456    elfBinGen64.addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 8,
457                ".dynsym", SHT_DYNSYM, SHF_ALLOC, 0, 1, Elf64Types::nobase));
458    elfBinGen64.addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 4,
459                ".hash", SHT_HASH, SHF_ALLOC,
460                mainBuiltinSectTable[ELFSECTID_DYNSYM-ELFSECTID_START], 0,
461                Elf64Types::nobase));
462    elfBinGen64.addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 1, ".dynstr", SHT_STRTAB,
463                SHF_ALLOC, 0, 0, Elf64Types::nobase));
464    // '.text' with alignment=4096
465    elfBinGen64.addRegion(ElfRegion64(input->codeSize, (const cxbyte*)input->code, 
466              0x1000, ".text", SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR, 0, 0,
467              Elf64Types::nobase, 0, false, 256));
468    elfBinGen64.addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 0x1000,
469                ".dynamic", SHT_DYNAMIC, SHF_ALLOC|SHF_WRITE,
470                mainBuiltinSectTable[ELFSECTID_DYNSTR-ELFSECTID_START], 0,
471                Elf64Types::nobase, 0, false, 8));
472    if (!input->newBinFormat)
473    {
474        elfBinGen64.addRegion(ElfRegion64::noteSection());
475        elfBinGen64.addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 1,
476                    ".AMDGPU.config", SHT_PROGBITS, 0));
477    }
478    elfBinGen64.addRegion(ElfRegion64(commentSize, (const cxbyte*)comment, 1, ".comment",
479              SHT_PROGBITS, SHF_MERGE|SHF_STRINGS, 0, 0, 0, 1));
480    elfBinGen64.addRegion(ElfRegion64(0, (const cxbyte*)nullptr, 8,
481                ".symtab", SHT_SYMTAB, 0, 0, 1));
482    elfBinGen64.addRegion(ElfRegion64::shstrtabSection());
483    elfBinGen64.addRegion(ElfRegion64::strtabSection());
484    elfBinGen64.addRegion(ElfRegion64::sectionHeaderTable());
485   
486    /* extra sections */
487    for (const BinSection& section: input->extraSections)
488        elfBinGen64.addRegion(ElfRegion64(section, mainBuiltinSectTable,
489                         ROCMSECTID_MAX, mainSectionsNum));
490    /* extra symbols */
491    for (const BinSymbol& symbol: input->extraSymbols)
492        elfBinGen64.addSymbol(ElfSymbol64(symbol, mainBuiltinSectTable,
493                         ROCMSECTID_MAX, mainSectionsNum));
494   
495    size_t binarySize = elfBinGen64.countSize();
496    /****
497     * prepare for write binary to output
498     ****/
499    std::unique_ptr<std::ostream> outStreamHolder;
500    std::ostream* os = nullptr;
501    if (aPtr != nullptr)
502    {
503        aPtr->resize(binarySize);
504        outStreamHolder.reset(
505                new ArrayOStream(binarySize, reinterpret_cast<char*>(aPtr->data())));
506        os = outStreamHolder.get();
507    }
508    else if (vPtr != nullptr)
509    {
510        vPtr->resize(binarySize);
511        outStreamHolder.reset(new VectorOStream(*vPtr));
512        os = outStreamHolder.get();
513    }
514    else // from argument
515        os = osPtr;
516   
517    const std::ios::iostate oldExceptions = os->exceptions();
518    try
519    {
520    os->exceptions(std::ios::failbit | std::ios::badbit);
521    /****
522     * write binary to output
523     ****/
524    FastOutputBuffer bos(256, *os);
525    elfBinGen64.generate(bos);
526    assert(bos.getWritten() == binarySize);
527    }
528    catch(...)
529    {
530        os->exceptions(oldExceptions);
531        throw;
532    }
533    os->exceptions(oldExceptions);
534}
535
536void ROCmBinGenerator::generate(Array<cxbyte>& array) const
537{
538    generateInternal(nullptr, nullptr, &array);
539}
540
541void ROCmBinGenerator::generate(std::ostream& os) const
542{
543    generateInternal(&os, nullptr, nullptr);
544}
545
546void ROCmBinGenerator::generate(std::vector<char>& v) const
547{
548    generateInternal(nullptr, &v, nullptr);
549}
Note: See TracBrowser for help on using the repository browser.