summaryrefslogtreecommitdiffstats
path: root/src/coff/base/coff_object.h
blob: 8b98129b29fdedd1714fef251d5da55d16f88d0b (plain)
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/***************************************************************************
 *   Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org>                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
#ifndef COFF_OBJECT_H
#define COFF_OBJECT_H

#include "coff.h"
#include "devices/base/register.h"

namespace Coff
{
//----------------------------------------------------------------------------
extern bool getName(const QByteArray &data, uint &offset, uint nbChars, uint stringTableOffset, Log::Base &log, QString &name);
extern int disassemble(long int opcode, long int opcode2, int org, Pic::Architecture architecture, char *buffer, size_t sizeof_buffer);

BEGIN_DECLARE_ENUM(OptHeaderFormat)
  OldMicrochip = 0, NewMicrochip, Picc, Ccsc
END_DECLARE_ENUM_STD(OptHeaderFormat)

struct OptHeaderData {
  uint magic;
  OptHeaderFormat optHeaderFormat;
  bool parsed;
};
extern const OptHeaderData OPT_HEADER_DATA[];

class Object;
class Section;

//----------------------------------------------------------------------------
class Element
{
public:
  Element(const Object &object) : _object(object) {}
  virtual ~Element() {}

protected:
  const Object &_object;
};

//----------------------------------------------------------------------------
class BaseSymbol : public Element
{
public:
  BaseSymbol(const Object &object) : Element(object) {}
  virtual bool isAuxSymbol() const = 0;
};

BEGIN_DECLARE_ENUM(AuxSymbolType)
  Direct = 0, File, Identifier, Section
END_DECLARE_ENUM_STD(AuxSymbolType)

class AuxSymbol : public BaseSymbol
{
public:
  virtual bool isAuxSymbol() const { return true; }
  static AuxSymbol *factory(const Object &object, AuxSymbolType type, const QByteArray &data,
                            uint offset, uint stringTableOffset, Log::Base &log);

public:
  AuxSymbol(const Object &object) : BaseSymbol(object) {}
  virtual AuxSymbolType type() const = 0;
};

class AuxSymbolDirect : public AuxSymbol
{
public:
  AuxSymbolDirect(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log);
  virtual AuxSymbolType type() const { return AuxSymbolType::Direct; }

private:
  uchar   _command;
  QString _string;
};

class AuxSymbolFile : public AuxSymbol
{
public:
  AuxSymbolFile(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log);
  virtual AuxSymbolType type() const { return AuxSymbolType::File; }
  QString filename() const { return _filename; }
  uint line() const { return _line; }

private:
  uint    _line;
  QString _filename;
};

class AuxSymbolIdentifier : public AuxSymbol
{
public:
  AuxSymbolIdentifier(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log);
  virtual AuxSymbolType type() const { return AuxSymbolType::Identifier; }
  QString string() const { return _string; }

private:
  QString _string;
};

class AuxSymbolSection : public AuxSymbol
{
public:
  AuxSymbolSection(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log);
  virtual AuxSymbolType type() const { return AuxSymbolType::Section; }

private:
  uint _length, _nbRelocations, _nbLineNumbers;
};

class AuxSymbolUnknown : public AuxSymbol
{
public:
  AuxSymbolUnknown(const Object &object) : AuxSymbol(object) {}
  virtual AuxSymbolType type() const { return AuxSymbolType::Nb_Types; }
};

//----------------------------------------------------------------------------
BEGIN_DECLARE_ENUM(SymbolSectionType)
  InsideSection = 0, UndefinedSection, AbsoluteValue, DebugSymbol
END_DECLARE_ENUM_STD(SymbolSectionType)

struct SymbolClassData {
  const char *key, *label;
  uint id;
};
BEGIN_DECLARE_ENUM(SymbolClass)
  Automatic = 0, External, Static, Register, ExternalDefinition,
  Label, UndefinedLabel, MemberOfStructure, FunctionArgument, StructureTag,
  MemberOfUnion, UnionTag, TypeDefinition, UndefinedStatic, EnumerationTag,
  MemberOfEnumeration, RegisterParameter, BitField, AutoArgument, EndOfBlock,
  BeginEndOfBlock, BeginEndOfFunction, EndOfStructure, Filename, LineNumber,
  DuplicateTag, Section
END_DECLARE_ENUM(SymbolClass, SymbolClassData)

struct SymbolTypeData {
  const char *key, *label;
  uint id;
};
BEGIN_DECLARE_ENUM(SymbolType)
  Void = 0, Char, Short, Int, Long, Float, Double, Struct, Union,
  Enum, MemberOfEnum, UChar, UShort, UInt, ULong, LongDouble
END_DECLARE_ENUM(SymbolType, SymbolTypeData)

struct SymbolDerivedTypeData {
  const char *key, *label;
  uint id;
};
BEGIN_DECLARE_ENUM(SymbolDerivedType)
  Pointer = 0, Function, Array
END_DECLARE_ENUM(SymbolDerivedType, SymbolDerivedTypeData)

class Symbol : public BaseSymbol
{
public:
  Symbol(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset,
         const QString &lastFilename, Log::Base &log);
  virtual bool isAuxSymbol() const { return false; }
  QString name() const { return _name; }
  QString filename() const { return _filename; }
  const QValueVector<AuxSymbol *> &auxSymbols() const { return _aux; }
  SymbolClass symbolClass() const { return _sclass; }
  SymbolSectionType sectionType() const;
  SymbolType type() const { return _type; }
  SymbolDerivedType derivedType() const { return _dtype; }
  uint value() const { return _value; }
  uint section() const { Q_ASSERT( sectionType()==SymbolSectionType::InsideSection ); return _section; }

private:
  QString _name, _filename;
  uint _value, _section;
  SymbolClass _sclass;
  SymbolType  _type;
  SymbolDerivedType _dtype;
  QValueVector<AuxSymbol *> _aux;
};

//----------------------------------------------------------------------------
class Relocation : public Element
{
public:
  Relocation(const Object &object, const Section &section, const QByteArray &data,
             uint offset, Log::Base &log);

private:
  ulong  _address, _type;
  short  _offset;
  const Symbol *_symbol;
};

//----------------------------------------------------------------------------
class CodeLine : public Element
{
public:
  CodeLine(const Object &object, const Section &section, const QByteArray &data,
           uint offset, const QString &lastFilename, Log::Base &log);
  const Section &section() const { return _section; }
  QString filename() const { return _filename; }
  uint line() const { return _line; }
  Address address() const { return _address; }
  const Symbol *symbol() const { return _symbol; }

private:
  const Section &_section;
  uint           _line;
  Address        _address;
  QString        _filename;
  const Symbol  *_symbol;
};

//----------------------------------------------------------------------------
BEGIN_DECLARE_ENUM(SectionType)
  Config = 0, DeviceId, UserIds, UninitializedData, InitializedData, DataRom, Code
END_DECLARE_ENUM_STD(SectionType)

class Section : public Element
{
public:
  class InstructionData {
  public:
    BitValue value;
    QString opcode, disasm;
  };

public:
  Section(const Device::Data &device, const Object &object, const QByteArray &data, uint offset,
          uint stringTableOffset, Log::Base &log);
  ~Section();
  SectionType type() const;
  QString name() const { return _name; }
  Address address() const { return _address; }
  uint size() const { return _size; }
  uint flags() const { return _flags; }
  const QMap<Address, InstructionData> &instructions() const { return _instructions; }
  const QValueVector<Relocation *> &relocations() const { return _relocations; }
  const QValueVector<CodeLine *> &lines() const { return _lines; }

private:
  QString _name;
  Address _address;
  uint _size, _flags;
  QMap<Address, InstructionData> _instructions;
  QValueVector<Relocation *> _relocations;
  QValueVector<CodeLine *> _lines;

  enum Flag { FText = 0x00020, FData = 0x00040, FBSS = 0x00080, FDataRom = 0x00100,
              FAbs = 0x01000, FShared = 0x02000, FOverlay = 0x04000, FAccess = 0x08000,
              FActivationRecord = 0x10000 };
};

//----------------------------------------------------------------------------
class Object : public Base
{
public:
  Object(const Device::Data *device, const PURL::Url &url);
  virtual ~Object();
  virtual bool parse(Log::Base &log);
  Format format() const { return _format; }
  const Device::Data *device() const { return _device; }
  uint size(SizeType stype) const { return _format.data().sizes[stype]; }
  OptHeaderFormat optHeaderFormat() const { return _optHeaderFormat; }
  uint optHeaderMagic() const { return _optHeaderMagic; }
  uint nbSymbols() const { return _symbols.count(); }
  const BaseSymbol *symbol(uint i) const { return _symbols[i]; }
  const Symbol *symbol(const QString &name) const { return (_msymbols.contains(name) ? _msymbols[name] : 0); }
  uint nbSections() const { return _sections.count(); }
  const Section *section(uint i) const { return _sections[i]; }
  const QStringList &filenames() const { return _filenames; }
  const QMap<QString, Address> &variables() const { return _variables; }
  QString variableName(Address address) const;

  enum Flag { RelocationStripped = 0x0001, Executable = 0x0002, LineNumberStripped = 0x0004,
              SymbolStripped = 0x0080, Extended18 = 0x4000, Generic = 0x8000 };
  Q_DECLARE_FLAGS(Flags, Flag)

protected:
  Q_UINT32                _optHeaderMagic;
  OptHeaderFormat         _optHeaderFormat;
  const Device::Data     *_device;
  uint                    _nbSections, _nbSymbols, _symbolOffset;
  Flags                   _flags;
  QValueVector<BaseSymbol *> _symbols;
  QMap<QString, Symbol *>  _msymbols; // name -> Symbol *
  QValueVector<Section *> _sections;
  QStringList             _filenames;
  QMap<QString, Address>  _variables; // name -> address

  virtual bool parseHeader(const QByteArray &data, uint &offset, Log::Base &log);
  virtual bool parseOptionnalHeader(const QByteArray &data, uint &offset, Log::Base &log);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Object::Flags)

} // namespace

//----------------------------------------------------------------------------
namespace Pic
{

class RegisterNameData
{
public:
  RegisterNameData() {}
  RegisterNameData(const QString &label, const Register::TypeData &data) : _label(label), _data(data) {}
  QString label() const { return _label; }
  const Register::TypeData &data() const { return _data; }
  bool operator <(const RegisterNameData &rnd) const { return _label<rnd._label; };

private:
  QString _label;
  Register::TypeData _data;
};
extern QValueVector<RegisterNameData> sfrList(const Pic::Data &data);
extern QValueVector<RegisterNameData> gprList(const Pic::Data &data, const Coff::Object *coff);
extern QValueVector<RegisterNameData> variableList(const Pic::Data &data, const Coff::Object &coff);

} // namespace

#endif