source: CLRX/CLRadeonExtender/trunk/CLRX/amdasm/Disassembler.h @ 2525

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

CLRadeonExtender: Disasm: Split beforeDisassemble into three parts (second is overridable). Use startOffset in storing label addresses.

File size: 15.3 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/*! \file Disassembler.h
20 * \brief an disassembler for Radeon GPU's
21 */
22
23#ifndef __CLRX_DISASSEMBLER_H__
24#define __CLRX_DISASSEMBLER_H__
25
26#include <CLRX/Config.h>
27#include <string>
28#include <istream>
29#include <ostream>
30#include <vector>
31#include <utility>
32#include <memory>
33#include <CLRX/amdbin/AmdBinaries.h>
34#include <CLRX/amdbin/AmdCL2Binaries.h>
35#include <CLRX/amdbin/ROCmBinaries.h>
36#include <CLRX/amdbin/GalliumBinaries.h>
37#include <CLRX/amdbin/AmdBinGen.h>
38#include <CLRX/amdasm/Commons.h>
39#include <CLRX/utils/Utilities.h>
40#include <CLRX/utils/InputOutput.h>
41
42/// main namespace
43namespace CLRX
44{
45
46class Disassembler;
47
48enum: Flags
49{
50    DISASM_DUMPCODE = 1,    ///< dump code
51    DISASM_METADATA = 2,    ///< dump metadatas
52    DISASM_DUMPDATA = 4,    ///< dump datas
53    DISASM_CALNOTES = 8,    ///< dump ATI CAL notes
54    DISASM_FLOATLITS = 16,  ///< print in comments float literals
55    DISASM_HEXCODE = 32,    ///< print on left side hexadecimal code
56    DISASM_SETUP = 64,
57    DISASM_CONFIG = 128,    ///< print kernel configuration instead raw data
58    DISASM_BUGGYFPLIT = 256,
59   
60    ///< all disassembler flags (without config)
61    DISASM_ALL = FLAGS_ALL&(~(DISASM_CONFIG|DISASM_BUGGYFPLIT))
62};
63
64struct GCNDisasmUtils;
65
66/// main class for
67class ISADisassembler: public NonCopyableAndNonMovable
68{
69private:
70    friend struct GCNDisasmUtils; // INTERNAL LOGIC
71protected:
72    /// internal relocation structure
73    struct Relocation
74    {
75        size_t symbol;   ///< symbol index
76        RelocType type; ///< relocation type
77        int64_t addend; ///< relocation addend
78    };
79   
80    typedef std::vector<size_t>::const_iterator LabelIter;  ///< label iterator
81   
82    /// relocation iterator
83    typedef std::vector<std::pair<size_t, Relocation> >::const_iterator RelocIter;
84   
85    /// named label iterator
86    typedef std::vector<std::pair<size_t, CString> >::const_iterator NamedLabelIter;
87   
88    Disassembler& disassembler; ///< disassembler instance
89    size_t startOffset; ///< start offset
90    size_t inputSize;   ///< size of input
91    const cxbyte* input;    ///< input code
92    bool dontPrintLabelsAfterCode;
93    std::vector<size_t> labels; ///< list of local labels
94    std::vector<std::pair<size_t, CString> > namedLabels;   ///< named labels
95    std::vector<CString> relSymbols;    ///< symbols used by relocations
96    std::vector<std::pair<size_t, Relocation> > relocations;    ///< relocations
97    FastOutputBuffer output;    ///< output buffer
98   
99    /// constructor
100    explicit ISADisassembler(Disassembler& disassembler, cxuint outBufSize = 500);
101   
102    /// write all labels before specified position
103    void writeLabelsToPosition(size_t pos, LabelIter& labelIter,
104               NamedLabelIter& namedLabelIter);
105    /// write all labels to end
106    void writeLabelsToEnd(size_t start, LabelIter labelIter, NamedLabelIter namedLabelIter);
107    /// write location in the code
108    void writeLocation(size_t pos);
109    /// write relocation to current place in instruction
110    bool writeRelocation(size_t pos, RelocIter& relocIter);
111   
112public:
113    virtual ~ISADisassembler();
114   
115    /// set input code
116    void setInput(size_t inputSize, const cxbyte* input, size_t startOffset = 0)
117    {
118        this->inputSize = inputSize;
119        this->input = input;
120        this->startOffset = startOffset;
121    }
122   
123    void setDontPrintLabels(bool after)
124    { dontPrintLabelsAfterCode = after; }
125   
126    /// analyze code before disassemblying
127    virtual void analyzeBeforeDisassemble() = 0;
128   
129    /// first part before disassemble - clear numbered labels
130    void clearNumberedLabels();
131    /// last part before disassemble - prepare labels (sorting)
132    void prepareLabelsAndRelocations();
133    /// makes some things before disassemblying
134    void beforeDisassemble();
135    /// disassembles input code
136    virtual void disassemble() = 0;
137
138    /// add named label to list (must be called before disassembly)
139    void addNamedLabel(size_t pos, const CString& name)
140    { namedLabels.push_back(std::make_pair(pos, name)); }
141    /// add named label to list (must be called before disassembly)
142    void addNamedLabel(size_t pos, CString&& name)
143    { namedLabels.push_back(std::make_pair(pos, name)); }
144   
145    /// add symbol to relocations
146    size_t addRelSymbol(const CString& symName)
147    {
148        size_t index = relSymbols.size();
149        relSymbols.push_back(symName);
150        return index;
151    }
152    /// add relocation
153    void addRelocation(size_t offset, RelocType type, size_t symIndex, int64_t addend)
154    { relocations.push_back(std::make_pair(offset, Relocation{symIndex, type, addend})); }
155    /// clear all relocations
156    void clearRelocations()
157    {
158        relSymbols.clear();
159        relocations.clear();
160    }
161};
162
163/// GCN architectur dissassembler
164class GCNDisassembler: public ISADisassembler
165{
166private:
167    bool instrOutOfCode;
168   
169    friend struct GCNDisasmUtils; // INTERNAL LOGIC
170public:
171    /// constructor
172    GCNDisassembler(Disassembler& disassembler);
173    /// destructor
174    ~GCNDisassembler();
175   
176    /// analyze code before disassemblying
177    void analyzeBeforeDisassemble();
178    /// disassemble code
179    void disassemble();
180};
181
182/// single kernel input for disassembler
183/** all pointer members holds only pointers that should be freed by your routines.
184 * No management of data */
185struct AmdDisasmKernelInput
186{
187    CString kernelName; ///< kernel name
188    size_t metadataSize;    ///< metadata size
189    const char* metadata;   ///< kernel's metadata
190    size_t headerSize;  ///< kernel header size
191    const cxbyte* header;   ///< kernel header size
192    std::vector<CALNoteInput> calNotes;   ///< ATI CAL notes
193    size_t dataSize;    ///< data (from inner binary) size
194    const cxbyte* data; ///< data from inner binary
195    size_t codeSize;    ///< size of code of kernel
196    const cxbyte* code; ///< code of kernel
197};
198
199/// whole disassembler input (for AMD Catalyst driver GPU binaries)
200/** all pointer members holds only pointers that should be freed by your routines.
201 * No management of data */
202struct AmdDisasmInput
203{
204    GPUDeviceType deviceType;   ///< GPU device type
205    bool is64BitMode;       ///< true if 64-bit mode of addressing
206    CString driverInfo; ///< driver info (for AMD Catalyst drivers)
207    CString compileOptions; ///< compile options which used by in clBuildProgram
208    size_t globalDataSize;  ///< global (constants for kernels) data size
209    const cxbyte* globalData;   ///< global (constants for kernels) data
210    std::vector<AmdDisasmKernelInput> kernels;    ///< kernel inputs
211};
212
213/// relocation with addend
214struct AmdCL2RelaEntry
215{
216    size_t offset;  ///< offset
217    RelocType type; ///< relocation type
218    cxuint symbol;  ///< symbol
219    int64_t addend; ///< addend
220};
221
222/// single kernel input for disassembler
223/** all pointer members holds only pointers that should be freed by your routines.
224 * No management of data */
225struct AmdCL2DisasmKernelInput
226{
227    CString kernelName; ///< kernel name
228    size_t metadataSize;    ///< metadata size
229    const cxbyte* metadata;   ///< kernel's metadata
230    size_t isaMetadataSize;    ///< metadata size
231    const cxbyte* isaMetadata;   ///< kernel's metadata
232    size_t setupSize;    ///< data (from inner binary) size
233    const cxbyte* setup; ///< data from inner binary
234    size_t stubSize;    ///< data (from inner binary) size
235    const cxbyte* stub; ///< data from inner binary
236    std::vector<AmdCL2RelaEntry> textRelocs;    ///< text relocations
237    size_t codeSize;    ///< size of code of kernel
238    const cxbyte* code; ///< code of kernel
239};
240
241/// whole disassembler input (for AMD Catalyst driver GPU binaries)
242/** all pointer members holds only pointers that should be freed by your routines.
243 * No management of data */
244struct AmdCL2DisasmInput
245{
246    GPUDeviceType deviceType;   ///< GPU device type
247    uint32_t archMinor;     ///< GPU arch minor
248    uint32_t archStepping;     ///< GPU arch stepping
249    cxuint driverVersion; ///< driver version
250    CString compileOptions; ///< compile options which used by in clBuildProgram
251    CString aclVersionString; ///< acl version string
252    size_t globalDataSize;  ///< global (constants for kernels) data size
253    const cxbyte* globalData;   ///< global (constants for kernels) data
254    size_t rwDataSize;  ///< global rw data size
255    const cxbyte* rwData;   ///< global rw data data
256    size_t bssAlignment;    ///< alignment of global bss section
257    size_t bssSize;         ///< size of global bss section
258    size_t samplerInitSize;     ///< sampler init data size
259    const cxbyte* samplerInit;  ///< sampler init data
260   
261    /// sampler relocations
262    std::vector<std::pair<size_t, size_t> > samplerRelocs;
263    std::vector<AmdCL2DisasmKernelInput> kernels;    ///< kernel inputs
264};
265
266struct ROCmDisasmKernelInput
267{
268    CString kernelName; ///< kernel name
269    const cxbyte* setup;
270    size_t codeSize;
271    size_t offset;
272};
273
274/// disasm ROCm region
275struct ROCmDisasmRegionInput
276{
277    CString regionName; ///< region name
278    size_t size;    ///< region size
279    size_t offset;  ///< region offset in code
280    bool isKernel;  ///< true if kernel
281};
282
283struct ROCmDisasmInput
284{
285    GPUDeviceType deviceType;   ///< GPU device type
286    uint32_t archMinor;     ///< GPU arch minor
287    uint32_t archStepping;     ///< GPU arch stepping
288    std::vector<ROCmDisasmRegionInput> regions;  ///< regions
289    size_t codeSize;    ///< code size
290    const cxbyte* code; ///< code
291};
292
293/// disasm kernel info structure (Gallium binaries)
294struct GalliumDisasmKernelInput
295{
296    CString kernelName;   ///< kernel's name
297    GalliumProgInfoEntry progInfo[3];   ///< program info for kernel
298    uint32_t offset;    ///< offset of kernel code
299    std::vector<GalliumArgInfo> argInfos;   ///< arguments
300};
301
302/// whole disassembler input (for Gallium driver GPU binaries)
303struct GalliumDisasmInput
304{
305    GPUDeviceType deviceType;   ///< GPU device type
306    bool is64BitMode;       ///< true if 64-bit mode of addressing
307    size_t globalDataSize;  ///< global (constants for kernels) data size
308    const cxbyte* globalData;   ///< global (constants for kernels) data
309    std::vector<GalliumDisasmKernelInput> kernels;    ///< list of input kernels
310    size_t codeSize;    ///< code size
311    const cxbyte* code; ///< code
312};
313
314/// disassembler input for raw code
315struct RawCodeInput
316{
317    GPUDeviceType deviceType;   ///< GPU device type
318    size_t codeSize;            ///< code size
319    const cxbyte* code;         ///< code
320};
321
322/// disassembler class
323class Disassembler: public NonCopyableAndNonMovable
324{
325private:
326    friend class ISADisassembler;
327    std::unique_ptr<ISADisassembler> isaDisassembler;
328    bool fromBinary;
329    BinaryFormat binaryFormat;
330    union {
331        const AmdDisasmInput* amdInput;
332        const AmdCL2DisasmInput* amdCL2Input;
333        const GalliumDisasmInput* galliumInput;
334        const ROCmDisasmInput* rocmInput;
335        const RawCodeInput* rawInput;
336    };
337    std::ostream& output;
338    Flags flags;
339    size_t sectionCount;
340public:
341    /// constructor for 32-bit GPU binary
342    /**
343     * \param binary main GPU binary
344     * \param output output stream
345     * \param flags flags for disassembler
346     */
347    Disassembler(const AmdMainGPUBinary32& binary, std::ostream& output,
348                 Flags flags = 0);
349    /// constructor for 64-bit GPU binary
350    /**
351     * \param binary main GPU binary
352     * \param output output stream
353     * \param flags flags for disassembler
354     */
355    Disassembler(const AmdMainGPUBinary64& binary, std::ostream& output,
356                 Flags flags = 0);
357    /// constructor for AMD OpenCL 2.0 GPU binary
358    /**
359     * \param binary main GPU binary
360     * \param output output stream
361     * \param flags flags for disassembler
362     */
363    Disassembler(const AmdCL2MainGPUBinary& binary, std::ostream& output,
364                 Flags flags = 0);
365    /// constructor for ROCm GPU binary
366    /**
367     * \param binary main GPU binary
368     * \param output output stream
369     * \param flags flags for disassembler
370     */
371    Disassembler(const ROCmBinary& binary, std::ostream& output, Flags flags = 0);
372    /// constructor for AMD disassembler input
373    /**
374     * \param disasmInput disassembler input object
375     * \param output output stream
376     * \param flags flags for disassembler
377     */
378    Disassembler(const AmdDisasmInput* disasmInput, std::ostream& output,
379                 Flags flags = 0);
380    /// constructor for AMD OpenCL 2.0 disassembler input
381    /**
382     * \param disasmInput disassembler input object
383     * \param output output stream
384     * \param flags flags for disassembler
385     */
386    Disassembler(const AmdCL2DisasmInput* disasmInput, std::ostream& output,
387                 Flags flags = 0);
388    /// constructor for ROCMm disassembler input
389    /**
390     * \param disasmInput disassembler input object
391     * \param output output stream
392     * \param flags flags for disassembler
393     */
394    Disassembler(const ROCmDisasmInput* disasmInput, std::ostream& output,
395                 Flags flags = 0);
396   
397    /// constructor for bit GPU binary from Gallium
398    /**
399     * \param deviceType GPU device type
400     * \param binary main GPU binary
401     * \param output output stream
402     * \param flags flags for disassembler
403     */
404    Disassembler(GPUDeviceType deviceType, const GalliumBinary& binary,
405                 std::ostream& output, Flags flags = 0);
406   
407    /// constructor for Gallium disassembler input
408    /**
409     * \param disasmInput disassembler input object
410     * \param output output stream
411     * \param flags flags for disassembler
412     */
413    Disassembler(const GalliumDisasmInput* disasmInput, std::ostream& output,
414                 Flags flags = 0);
415   
416    /// constructor for raw code
417    Disassembler(GPUDeviceType deviceType, size_t rawCodeSize, const cxbyte* rawCode,
418                 std::ostream& output, Flags flags = 0);
419   
420    ~Disassembler();
421   
422    /// disassembles input
423    void disassemble();
424   
425    /// get disassemblers flags
426    Flags getFlags() const
427    { return flags; }
428    /// get disassemblers flags
429    void setFlags(Flags flags)
430    { this->flags = flags; }
431   
432    /// get deviceType
433    GPUDeviceType getDeviceType() const;
434   
435    /// get disassembler input
436    const AmdDisasmInput* getAmdInput() const
437    { return amdInput; }
438   
439    /// get disassembler input
440    const AmdCL2DisasmInput* getAmdCL2Input() const
441    { return amdCL2Input; }
442   
443    /// get disassembler input
444    const GalliumDisasmInput* getGalliumInput() const
445    { return galliumInput; }
446   
447    /// get output stream
448    const std::ostream& getOutput() const
449    { return output; }
450    /// get output stream
451    std::ostream& getOutput()
452    { return output; }
453};
454
455};
456
457#endif
Note: See TracBrowser for help on using the repository browser.