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

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

CLRadeonExtender: ROCmBinGen: Include different section indices in the symbols depends on the input configuration.

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