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