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

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

CLRadeonExtender: Correct size from symbol to kernel code size.

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