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

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

CLRadeonExtender: Delegate writeLabelsTo... to public API. fix dontPrintLabelsAfterCode.
ROCm: Print labels between data regions and config.

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