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

Last change on this file since 2530 was 2530, checked in by matszpk, 4 years ago

CLRadeonExtender: next commenting the code. add data regions only for global symbols.

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 <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          regionsNum(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    regionsNum = 0;
49    const size_t symbolsNum = getSymbolsNum();
50    for (size_t i = 0; i < symbolsNum; i++)
51    {   // count regions number
52        const Elf64_Sym& sym = getSymbol(i);
53        const cxbyte symType = ELF64_ST_TYPE(sym.st_info);
54        const cxbyte bind = ELF64_ST_BIND(sym.st_info);
55        if (sym.st_shndx==textIndex &&
56            (symType==STT_GNU_IFUNC || (bind==STB_GLOBAL && symType==STT_OBJECT)))
57            regionsNum++;
58    }
59    if (code==nullptr && regionsNum!=0)
60        throw Exception("No code if regions number is not zero");
61    regions.reset(new ROCmRegion[regionsNum]);
62    size_t j = 0;
63    typedef std::pair<uint64_t, size_t> RegionOffsetEntry;
64    std::unique_ptr<RegionOffsetEntry[]> symOffsets(new RegionOffsetEntry[regionsNum]);
65   
66    for (size_t i = 0; i < symbolsNum; i++)
67    {
68        const Elf64_Sym& sym = getSymbol(i);
69        if (sym.st_shndx!=textIndex)
70            continue;   // if not in '.text' section
71        const size_t value = ULEV(sym.st_value);
72        if (value < codeOffset)
73            throw Exception("Region offset is too small!");
74        const size_t size = ULEV(sym.st_size);
75       
76        const cxbyte symType = ELF64_ST_TYPE(sym.st_info);
77        const cxbyte bind = ELF64_ST_BIND(sym.st_info);
78        if (symType==STT_GNU_IFUNC || (bind==STB_GLOBAL && symType==STT_OBJECT))
79        {
80            const bool isKernel = (symType==STT_GNU_IFUNC);
81            symOffsets[j] = std::make_pair(value, j);
82            if (isKernel && value+0x100 > codeOffset+codeSize)
83                throw Exception("Kernel offset is too big!");
84            regions[j++] = { getSymbolName(i), size, value, isKernel };
85        }
86    }
87    std::sort(symOffsets.get(), symOffsets.get()+regionsNum,
88            [](const RegionOffsetEntry& a, const RegionOffsetEntry& b)
89            { return a.first < b.first; });
90    // checking distance between regions
91    for (size_t i = 1; i <= regionsNum; i++)
92    {
93        size_t end = (i<regionsNum) ? symOffsets[i].first : codeOffset+codeSize;
94        ROCmRegion& region = regions[symOffsets[i-1].second];
95        if (region.isKernel && symOffsets[i-1].first+0x100 > end)
96            throw Exception("Kernel size is too small!");
97       
98        const uint64_t regSize = end - symOffsets[i-1].first;
99        if (region.size==0)
100            region.size = regSize;
101        else
102            region.size = std::min(regSize, region.size);
103    }
104   
105    if (hasRegionMap())
106    {   // create region map
107        regionsMap.resize(regionsNum);
108        for (size_t i = 0; i < regionsNum; i++)
109            regionsMap[i] = std::make_pair(regions[i].regionName, i);
110        mapSort(regionsMap.begin(), regionsMap.end());
111    }
112}
113
114const ROCmRegion& ROCmBinary::getRegion(const char* name) const
115{
116    RegionMap::const_iterator it = binaryMapFind(regionsMap.begin(),
117                             regionsMap.end(), name);
118    if (it == regionsMap.end())
119        throw Exception("Can't find region name");
120    return regions[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.