summaryrefslogtreecommitdiff
path: root/wasm.h
blob: 0bb626910d40d2d08da123ce70ae5460dcebd1e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#ifndef WASM_H
#define WASM_H

#include "instr.h"
#include <libdwarf/libdwarf.h>
#include <QHash>
#include <QObject>
#include <QString>
#include <QVariant>
#include <QVector>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include "types.h"

enum class WasmType
{
    i32,
    i64,
    f32,
    f64
};

struct WasmGlobal
{
    WasmType type;
    bool mutability;
    bool operator==(const WasmGlobal &other) const
    {
        return type == other.type
            && mutability == other.mutability;
    }
};

struct WasmLocal
{
    WasmType type;
    bool operator==(const WasmLocal &other) const
    {
        return type == other.type;
    }
};

struct WasmParam
{
    QString name, dwtype;
    WasmType type;
    bool operator==(const WasmParam &other) const
    {
        return type == other.type
            && name == other.name
            && dwtype == other.dwtype;
    }
};

struct WasmRoutine
{
    QString name;
    quint32 lopc, hipc;
    QVector<WasmParam> params;
    QVector<WasmLocal> locals;
    QVector<WasmInstr> instructions;
    bool operator==(const WasmRoutine &other) const
    {
        return name == other.name
            && lopc == other.lopc
            && hipc == other.hipc
            && params == other.params
            && locals == other.locals
            && instructions == other.instructions;
    }
};

Q_DECLARE_METATYPE(WasmGlobal);
Q_DECLARE_METATYPE(WasmLocal);
Q_DECLARE_METATYPE(WasmParam);
Q_DECLARE_METATYPE(WasmRoutine);

class Wasm
{
public:
    Wasm();
    ~Wasm();
    int open(const QString &path, QString &error);
    const QVector<WasmGlobal> globals() const;
    QVariant routine(const QString &name) const;
    QVariant routine(quint32 addr) const;

private:

    struct section
    {
        varuint7 code;
        varuint32 len;
        QString name;
    };

    struct dwsection
    {
        quint32 offset;
        varuint32 len;
        QVector<Dwarf_Small> data;
        dwsection() : offset(0), len(0) {}
    };

    struct header
    {
        Dwarf_Sig8 type_signature;
        Dwarf_Unsigned cu_header_length, typeoffset, next_cu_header_offset;
        Dwarf_Half version_stamp, address_size, length_size, extension_size,
            header_cu_type;
        Dwarf_Off abbrev_offset;
    };

    struct attr
    {
        QString name;
        QVariant value;
    };

    enum
    {
        DEBUG_EMPTY,
        DEBUG_ABBREV,
        DEBUG_INFO,
        DEBUG_STR,
        DEBUG_ARANGES,
        DEBUG_FRAME,
        DEBUG_LINE,
        DEBUG_LOC,
        DEBUG_MACINFO,
        DEBUG_PUBNAMES,
        DEBUG_PUBTYPES,
        DEBUG_RANGES,
        DEBUG_TYPES,

        NSECTIONS
    };

    int parse(QString &error);
    int parse_global(QString &error);
    int parse_import(QString &error);
    int parse_code(QString &error);
    int parse_body(varuint32 index, QString &error);
    int parse_name(QString &error, varuint32 len);
    int parse_fname(QString &error, varuint32 maxlen);
    int get_type(value_type type, WasmType &wtype) const;
    int check_header(QString &error) const;
    int read_section(QString &error);
    int parse_header(section &s, QString &error) const;
    int read_name(QString &name, QString &error) const;
    dwsection *getdws(const QString &name);
    int skip(const section &s, QString &error) const;
    int read_dwarf(const Dwarf_Debug dbg,
        header &h, Dwarf_Error &e, QString &error);
    int read_child(Dwarf_Debug dbg,
        Dwarf_Die die, Dwarf_Error &e, QString &error);
    int process_die(Dwarf_Debug dbg,
        Dwarf_Die die, Dwarf_Error &e, QString &error);
    int read_attr(Dwarf_Attribute a, Dwarf_Error &e, QString &error,
        attr &attr);

    static bool isformstring(Dwarf_Half form);
    static bool isformaddr(Dwarf_Half form);
    static bool isformudata(Dwarf_Half form);
    static bool isformsdata(Dwarf_Half form);

    static int load_section(void *const obj, const Dwarf_Half section_index,
        Dwarf_Small **const return_data, int *const error);
    static int get_section_info(void *const obj, const Dwarf_Half section_index,
        Dwarf_Obj_Access_Section *const return_section, int *const error);
    static Dwarf_Unsigned get_section_count(void *const obj);

    FILE *f;
    long code_offset;
    varuint32 import_fncnt;
    dwsection sections[NSECTIONS];
    QVariant lastwr;
    QHash<varuint32, WasmRoutine> fmap;
    QVector<WasmGlobal> vglobals;
    static const char *const names[NSECTIONS];
};

#endif