source: CLRX/CLRadeonExtender/trunk/tests/amdbin/ROCmBinGen.cpp @ 3662

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

CLRadeonExtender: ROCm: Add eflags support (allow to set or get various e_flags value in ELF header).

File size: 5.6 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 <iostream>
22#include <sstream>
23#include <memory>
24#include <CLRX/utils/Containers.h>
25#include <CLRX/amdbin/ROCmBinaries.h>
26
27using namespace CLRX;
28
29static const char* origBinaryFiles[2] =
30{
31    CLRX_SOURCE_DIR "/tests/amdbin/rocmbins/consttest1-kaveri.hsaco.regen",
32    CLRX_SOURCE_DIR "/tests/amdbin/rocmbins/rijndael.hsaco.regen"
33};
34
35static ROCmInput genROCmInput(const ROCmBinary& binary)
36{
37    uint32_t archMajor = 0;
38    ROCmInput rocmInput;
39    rocmInput.eflags = ULEV(binary.getHeader().e_flags);
40    // try to get comment
41    try
42    {
43        const auto& commentHdr = binary.getSectionHeader(".comment");
44        rocmInput.commentSize = ULEV(commentHdr.sh_size);
45        rocmInput.comment = (const char*)binary.getSectionContent(".comment");
46    }
47    catch(...)
48    {
49        rocmInput.commentSize = 0;
50        rocmInput.comment = nullptr;
51    }
52    rocmInput.archMinor = 0;
53    rocmInput.archStepping = 0;
54   
55    {
56        // load .note to determine architecture (major, minor and stepping)
57        const cxbyte* noteContent = (const cxbyte*)binary.getNotes();
58        if (noteContent==nullptr)
59            throw Exception("Missing notes in inner binary!");
60        size_t notesSize = binary.getNotesSize();
61        // find note about AMDGPU
62        for (size_t offset = 0; offset < notesSize; )
63        {
64            const Elf64_Nhdr* nhdr = (const Elf64_Nhdr*)(noteContent + offset);
65            size_t namesz = ULEV(nhdr->n_namesz);
66            size_t descsz = ULEV(nhdr->n_descsz);
67            if (usumGt(offset, namesz+descsz, notesSize))
68                throw Exception("Note offset+size out of range");
69            if (ULEV(nhdr->n_type) == 0x3 && namesz==4 && descsz>=0x1a &&
70                ::strcmp((const char*)noteContent+offset+sizeof(Elf64_Nhdr), "AMD")==0)
71            {    // AMDGPU type
72                const uint32_t* content = (const uint32_t*)
73                        (noteContent+offset+sizeof(Elf64_Nhdr) + 4);
74                archMajor = ULEV(content[1]);
75                rocmInput.archMinor = ULEV(content[2]);
76                rocmInput.archStepping = ULEV(content[3]);
77            }
78            size_t align = (((namesz+descsz)&3)!=0) ? 4-((namesz+descsz)&3) : 0;
79            offset += sizeof(Elf64_Nhdr) + namesz + descsz + align;
80        }
81    }
82    // determine device type
83    rocmInput.deviceType = GPUDeviceType::CAPE_VERDE;
84    if (archMajor==0)
85        rocmInput.deviceType = GPUDeviceType::CAPE_VERDE;
86    else if (archMajor==7)
87        rocmInput.deviceType = GPUDeviceType::BONAIRE;
88    else if (archMajor==8)
89        rocmInput.deviceType = GPUDeviceType::ICELAND;
90    else if (archMajor==9)
91        rocmInput.deviceType = GPUDeviceType::GFX900;
92    // set main code to input
93    rocmInput.codeSize = binary.getCodeSize();
94    rocmInput.code = binary.getCode();
95   
96    // get ROCm symbol
97    const size_t codeOffset = binary.getCode()-binary.getBinaryCode();
98    for (size_t i = 0; i < binary.getRegionsNum(); i++)
99    {
100        const ROCmRegion& region = binary.getRegion(i);
101        rocmInput.symbols.push_back({region.regionName, region.offset-codeOffset,
102                    region.size, region.type});
103    }
104    return rocmInput;
105}
106
107static void testOrigBinary(cxuint testCase, const char* origBinaryFilename)
108{
109    Array<cxbyte> inputData;
110    Array<cxbyte> output;
111    std::string origBinFilenameStr(origBinaryFilename);
112    filesystemPath(origBinFilenameStr); // convert to system path (native separators)
113   
114    // load input binary
115    inputData = loadDataFromFile(origBinFilenameStr.c_str());
116    ROCmBinary rocmBin(inputData.size(), inputData.data(), 0);
117    // generate input from binary
118    ROCmInput rocmInput = genROCmInput(rocmBin);
119    ROCmBinGenerator binGen(&rocmInput);
120    binGen.generate(output);
121   
122    // compare generated output with input
123    if (output.size() != inputData.size())
124    {
125        std::ostringstream oss;
126            oss << "Failed for #" << testCase << " file=" << origBinaryFilename <<
127                    ": expectedSize=" << inputData.size() <<
128                    ", resultSize=" << output.size();
129        throw Exception(oss.str());
130    }
131    for (size_t i = 0; i < inputData.size(); i++)
132        if (output[i] != inputData[i])
133        {
134            std::ostringstream oss;
135            oss << "Failed for #" << testCase << " file=" << origBinaryFilename <<
136                    ": byte=" << i;
137            throw Exception(oss.str());
138        }
139}
140
141int main(int argc, const char** argv)
142{
143    int retVal = 0;
144    for (cxuint i = 0; i < sizeof(origBinaryFiles)/sizeof(const char*); i++)
145        try
146        { testOrigBinary(i, origBinaryFiles[i]); }
147        catch(const std::exception& ex)
148        {
149            std::cerr << ex.what() << std::endl;
150            retVal = 1;
151        }
152    return retVal;
153}
Note: See TracBrowser for help on using the repository browser.