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

Last change on this file since 2509 was 2509, checked in by matszpk, 3 years ago

CLRadeonExtender: Remove duplicate of 'return false'.

File size: 5.0 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
20#include <CLRX/Config.h>
21#include <cstdint>
22#include <map>
23#include <utility>
24#include <CLRX/amdbin/Elf.h>
25#include <CLRX/utils/Utilities.h>
26#include <CLRX/utils/MemAccess.h>
27#include <CLRX/amdbin/ROCmBinaries.h>
28
29using namespace CLRX;
30
31ROCmBinary::ROCmBinary(size_t binaryCodeSize, cxbyte* binaryCode, Flags creationFlags)
32        : ElfBinary64(binaryCodeSize, binaryCode, creationFlags),
33          kernelsNum(0), codeSize(0), code(nullptr)
34{
35    cxuint textIndex = SHN_UNDEF;
36    try
37    { textIndex = getSectionIndex(".text"); }
38    catch(const Exception& ex)
39    { } // ignore failed
40    uint64_t codeOffset = 0;
41    if (textIndex!=SHN_UNDEF)
42    {
43        code = getSectionContent(textIndex);
44        const Elf64_Shdr& textShdr = getSectionHeader(textIndex);
45        codeSize = ULEV(textShdr.sh_size);
46        codeOffset = ULEV(textShdr.sh_offset);
47    }
48   
49    kernelsNum = 0;
50    const size_t symbolsNum = getSymbolsNum();
51    for (size_t i = 0; i < symbolsNum; i++)
52    {
53        const Elf64_Sym& sym = getSymbol(i);
54        if (sym.st_shndx==textIndex)
55            kernelsNum++;
56    }
57    if (code==nullptr && kernelsNum!=0)
58        throw Exception("No code if kernels number is not zero");
59    kernels.reset(new ROCmKernel[kernelsNum]);
60    size_t j = 0;
61   
62    typedef std::pair<uint64_t, size_t> KernelOffsetEntry;
63    std::unique_ptr<KernelOffsetEntry[]> kernelOffsets(new KernelOffsetEntry[kernelsNum]);
64    for (size_t i = 0; i < symbolsNum; i++)
65    {
66        const Elf64_Sym& sym = getSymbol(i);
67        if (sym.st_shndx!=textIndex)
68            continue;
69        const size_t value = ULEV(sym.st_value);
70        if (value < codeOffset)
71            throw Exception("Kernel offset is too small!");
72        const size_t size = ULEV(sym.st_size);
73        if (value+0x100 > codeOffset+codeSize)
74            throw Exception("Kernel offset is too big!");
75        kernelOffsets[j] = std::make_pair(value, j);
76        kernels[j++] = { getSymbolName(i), value, size, value+0x100 };
77    }
78    std::sort(kernelOffsets.get(), kernelOffsets.get()+kernelsNum,
79            [](const KernelOffsetEntry& a, const KernelOffsetEntry& b)
80            { return a.first < b.first; });
81    // checking distance between kernels
82    for (size_t i = 1; i < kernelsNum; i++)
83    {
84        if (kernelOffsets[i-1].first+0x100 > kernelOffsets[i].first)
85            throw Exception("Kernel size is too small!");
86        ROCmKernel& kernel = kernels[kernelOffsets[i-1].second];
87        uint64_t kcodeSize = kernelOffsets[i].first - (kernelOffsets[i-1].first+0x100);
88        if (kernel.codeSize==0 && kcodeSize>0)
89            kernel.codeSize = kcodeSize;
90        if (kernel.codeSize > kcodeSize)
91            throw Exception("Kernel code size out of range");
92    }
93    {   // last kernel in position
94        if (kernelOffsets[kernelsNum-1].first+0x100 > codeOffset+codeSize)
95            throw Exception("Kernel size is too small!");
96        ROCmKernel& kernel = kernels[kernelOffsets[kernelsNum-1].second];
97        uint64_t kcodeSize = codeSize -
98                (kernelOffsets[kernelsNum-1].first+0x100-codeOffset);
99        if (kernel.codeSize==0 && kcodeSize>0)
100            kernel.codeSize = kcodeSize;
101        if (kernel.codeSize > kcodeSize)
102            throw Exception("Kernel code size out of range");
103    }
104   
105    if (hasKernelMap())
106    {   // create kernels map
107        kernelsMap.resize(kernelsNum);
108        for (size_t i = 0; i < kernelsNum; i++)
109            kernelsMap[i] = std::make_pair(kernels[i].kernelName, i);
110        mapSort(kernelsMap.begin(), kernelsMap.end());
111    }
112}
113
114const ROCmKernel& ROCmBinary::getKernel(const char* name) const
115{
116    KernelMap::const_iterator it = binaryMapFind(kernelsMap.begin(),
117                             kernelsMap.end(), name);
118    if (it == kernelsMap.end())
119        throw Exception("Can't find kernel name");
120    return kernels[it->second];
121}
122
123bool CLRX::isROCmBinary(size_t binarySize, const cxbyte* binary)
124{
125    if (!isElfBinary(binarySize, binary))
126        return false;
127    if (binary[EI_CLASS] != ELFCLASS64)
128        return false;
129    const Elf64_Ehdr* ehdr = reinterpret_cast<const Elf64_Ehdr*>(binary);
130    if (ULEV(ehdr->e_machine) != 0xe0 || ULEV(ehdr->e_flags)!=0)
131        return false;
132    return true;
133}
Note: See TracBrowser for help on using the repository browser.