Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- XCOFFObjectFile.h - XCOFF object file implementation -----*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file declares the XCOFFObjectFile class.
10
//
11
//===----------------------------------------------------------------------===//
12
 
13
#ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H
14
#define LLVM_OBJECT_XCOFFOBJECTFILE_H
15
 
16
#include "llvm/ADT/SmallString.h"
17
#include "llvm/ADT/SmallVector.h"
18
#include "llvm/BinaryFormat/XCOFF.h"
19
#include "llvm/Object/ObjectFile.h"
20
#include "llvm/Support/Endian.h"
21
#include <limits>
22
 
23
namespace llvm {
24
namespace object {
25
 
26
struct XCOFFFileHeader32 {
27
  support::ubig16_t Magic;
28
  support::ubig16_t NumberOfSections;
29
 
30
  // Unix time value, value of 0 indicates no timestamp.
31
  // Negative values are reserved.
32
  support::big32_t TimeStamp;
33
 
34
  support::ubig32_t SymbolTableOffset; // File offset to symbol table.
35
  support::big32_t NumberOfSymTableEntries;
36
  support::ubig16_t AuxHeaderSize;
37
  support::ubig16_t Flags;
38
};
39
 
40
struct XCOFFFileHeader64 {
41
  support::ubig16_t Magic;
42
  support::ubig16_t NumberOfSections;
43
 
44
  // Unix time value, value of 0 indicates no timestamp.
45
  // Negative values are reserved.
46
  support::big32_t TimeStamp;
47
 
48
  support::ubig64_t SymbolTableOffset; // File offset to symbol table.
49
  support::ubig16_t AuxHeaderSize;
50
  support::ubig16_t Flags;
51
  support::ubig32_t NumberOfSymTableEntries;
52
};
53
 
54
template <typename T> struct XCOFFAuxiliaryHeader {
55
  static constexpr uint8_t AuxiHeaderFlagMask = 0xF0;
56
  static constexpr uint8_t AuxiHeaderTDataAlignmentMask = 0x0F;
57
 
58
public:
59
  uint8_t getFlag() const {
60
    return static_cast<const T *>(this)->FlagAndTDataAlignment &
61
           AuxiHeaderFlagMask;
62
  }
63
 
64
  uint8_t getTDataAlignment() const {
65
    return static_cast<const T *>(this)->FlagAndTDataAlignment &
66
           AuxiHeaderTDataAlignmentMask;
67
  }
68
 
69
  uint16_t getVersion() const { return static_cast<const T *>(this)->Version; }
70
};
71
 
72
struct XCOFFAuxiliaryHeader32 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader32> {
73
  support::ubig16_t
74
      AuxMagic; ///< If the value of the o_vstamp field is greater than 1, the
75
                ///< o_mflags field is reserved for future use and it should
76
                ///< contain 0. Otherwise, this field is not used.
77
  support::ubig16_t
78
      Version; ///< The valid values are 1 and 2. When the o_vstamp field is 2
79
               ///< in an XCOFF32 file, the new interpretation of the n_type
80
               ///< field in the symbol table entry is used.
81
  support::ubig32_t TextSize;
82
  support::ubig32_t InitDataSize;
83
  support::ubig32_t BssDataSize;
84
  support::ubig32_t EntryPointAddr;
85
  support::ubig32_t TextStartAddr;
86
  support::ubig32_t DataStartAddr;
87
  support::ubig32_t TOCAnchorAddr;
88
  support::ubig16_t SecNumOfEntryPoint;
89
  support::ubig16_t SecNumOfText;
90
  support::ubig16_t SecNumOfData;
91
  support::ubig16_t SecNumOfTOC;
92
  support::ubig16_t SecNumOfLoader;
93
  support::ubig16_t SecNumOfBSS;
94
  support::ubig16_t MaxAlignOfText;
95
  support::ubig16_t MaxAlignOfData;
96
  support::ubig16_t ModuleType;
97
  uint8_t CpuFlag;
98
  uint8_t CpuType;
99
  support::ubig32_t MaxStackSize; ///< If the value is 0, the system default
100
                                  ///< maximum stack size is used.
101
  support::ubig32_t MaxDataSize;  ///< If the value is 0, the system default
102
                                  ///< maximum data size is used.
103
  support::ubig32_t
104
      ReservedForDebugger; ///< This field should contain 0. When a loaded
105
                           ///< program is being debugged, the memory image of
106
                           ///< this field may be modified by a debugger to
107
                           ///< insert a trap instruction.
108
  uint8_t TextPageSize;  ///< Specifies the size of pages for the exec text. The
109
                         ///< default value is 0 (system-selected page size).
110
  uint8_t DataPageSize;  ///< Specifies the size of pages for the exec data. The
111
                         ///< default value is 0 (system-selected page size).
112
  uint8_t StackPageSize; ///< Specifies the size of pages for the stack. The
113
                         ///< default value is 0 (system-selected page size).
114
  uint8_t FlagAndTDataAlignment;
115
  support::ubig16_t SecNumOfTData;
116
  support::ubig16_t SecNumOfTBSS;
117
};
118
 
119
struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader64> {
120
  support::ubig16_t AuxMagic;
121
  support::ubig16_t Version;
122
  support::ubig32_t ReservedForDebugger;
123
  support::ubig64_t TextStartAddr;
124
  support::ubig64_t DataStartAddr;
125
  support::ubig64_t TOCAnchorAddr;
126
  support::ubig16_t SecNumOfEntryPoint;
127
  support::ubig16_t SecNumOfText;
128
  support::ubig16_t SecNumOfData;
129
  support::ubig16_t SecNumOfTOC;
130
  support::ubig16_t SecNumOfLoader;
131
  support::ubig16_t SecNumOfBSS;
132
  support::ubig16_t MaxAlignOfText;
133
  support::ubig16_t MaxAlignOfData;
134
  support::ubig16_t ModuleType;
135
  uint8_t CpuFlag;
136
  uint8_t CpuType;
137
  uint8_t TextPageSize;
138
  uint8_t DataPageSize;
139
  uint8_t StackPageSize;
140
  uint8_t FlagAndTDataAlignment;
141
  support::ubig64_t TextSize;
142
  support::ubig64_t InitDataSize;
143
  support::ubig64_t BssDataSize;
144
  support::ubig64_t EntryPointAddr;
145
  support::ubig64_t MaxStackSize;
146
  support::ubig64_t MaxDataSize;
147
  support::ubig16_t SecNumOfTData;
148
  support::ubig16_t SecNumOfTBSS;
149
  support::ubig16_t XCOFF64Flag;
150
};
151
 
152
template <typename T> struct XCOFFSectionHeader {
153
  // Least significant 3 bits are reserved.
154
  static constexpr unsigned SectionFlagsReservedMask = 0x7;
155
 
156
  // The low order 16 bits of section flags denotes the section type.
157
  static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
158
 
159
public:
160
  StringRef getName() const;
161
  uint16_t getSectionType() const;
162
  bool isReservedSectionType() const;
163
};
164
 
165
// Explicit extern template declarations.
166
struct XCOFFSectionHeader32;
167
struct XCOFFSectionHeader64;
168
extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
169
extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
170
 
171
struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
172
  char Name[XCOFF::NameSize];
173
  support::ubig32_t PhysicalAddress;
174
  support::ubig32_t VirtualAddress;
175
  support::ubig32_t SectionSize;
176
  support::ubig32_t FileOffsetToRawData;
177
  support::ubig32_t FileOffsetToRelocationInfo;
178
  support::ubig32_t FileOffsetToLineNumberInfo;
179
  support::ubig16_t NumberOfRelocations;
180
  support::ubig16_t NumberOfLineNumbers;
181
  support::big32_t Flags;
182
};
183
 
184
struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
185
  char Name[XCOFF::NameSize];
186
  support::ubig64_t PhysicalAddress;
187
  support::ubig64_t VirtualAddress;
188
  support::ubig64_t SectionSize;
189
  support::big64_t FileOffsetToRawData;
190
  support::big64_t FileOffsetToRelocationInfo;
191
  support::big64_t FileOffsetToLineNumberInfo;
192
  support::ubig32_t NumberOfRelocations;
193
  support::ubig32_t NumberOfLineNumbers;
194
  support::big32_t Flags;
195
  char Padding[4];
196
};
197
 
198
struct LoaderSectionHeader32;
199
struct LoaderSectionHeader64;
200
struct LoaderSectionSymbolEntry32 {
201
  struct NameOffsetInStrTbl {
202
    support::big32_t IsNameInStrTbl; // Zero indicates name in string table.
203
    support::ubig32_t Offset;
204
  };
205
 
206
  char SymbolName[XCOFF::NameSize];
207
  support::ubig32_t Value; // The virtual address of the symbol.
208
  support::big16_t SectionNumber;
209
  uint8_t SymbolType;
210
  XCOFF::StorageClass StorageClass;
211
  support::ubig32_t ImportFileID;
212
  support::ubig32_t ParameterTypeCheck;
213
 
214
  Expected<StringRef>
215
  getSymbolName(const LoaderSectionHeader32 *LoaderSecHeader) const;
216
};
217
 
218
struct LoaderSectionSymbolEntry64 {
219
  support::ubig64_t Value; // The virtual address of the symbol.
220
  support::ubig32_t Offset;
221
  support::big16_t SectionNumber;
222
  uint8_t SymbolType;
223
  XCOFF::StorageClass StorageClass;
224
  support::ubig32_t ImportFileID;
225
  support::ubig32_t ParameterTypeCheck;
226
 
227
  Expected<StringRef>
228
  getSymbolName(const LoaderSectionHeader64 *LoaderSecHeader) const;
229
};
230
 
231
struct LoaderSectionRelocationEntry32 {
232
  support::ubig32_t VirtualAddr;
233
  support::big32_t SymbolIndex;
234
  support::ubig16_t Type;
235
  support::big16_t SectionNum;
236
};
237
 
238
struct LoaderSectionRelocationEntry64 {
239
  support::ubig64_t VirtualAddr;
240
  support::ubig16_t Type;
241
  support::big16_t SectionNum;
242
  support::big32_t SymbolIndex;
243
};
244
 
245
struct LoaderSectionHeader32 {
246
  support::ubig32_t Version;
247
  support::ubig32_t NumberOfSymTabEnt;
248
  support::ubig32_t NumberOfRelTabEnt;
249
  support::ubig32_t LengthOfImpidStrTbl;
250
  support::ubig32_t NumberOfImpid;
251
  support::big32_t OffsetToImpid;
252
  support::ubig32_t LengthOfStrTbl;
253
  support::big32_t OffsetToStrTbl;
254
 
255
  uint64_t getOffsetToSymTbl() const {
256
    return NumberOfSymTabEnt == 0 ? 0 : sizeof(LoaderSectionHeader32);
257
  }
258
 
259
  uint64_t getOffsetToRelEnt() const {
260
    // Relocation table is after Symbol table.
261
    return NumberOfRelTabEnt == 0
262
               ? 0
263
               : sizeof(LoaderSectionHeader32) +
264
                     sizeof(LoaderSectionSymbolEntry32) * NumberOfSymTabEnt;
265
  }
266
};
267
 
268
struct LoaderSectionHeader64 {
269
  support::ubig32_t Version;
270
  support::ubig32_t NumberOfSymTabEnt;
271
  support::ubig32_t NumberOfRelTabEnt;
272
  support::ubig32_t LengthOfImpidStrTbl;
273
  support::ubig32_t NumberOfImpid;
274
  support::ubig32_t LengthOfStrTbl;
275
  support::big64_t OffsetToImpid;
276
  support::big64_t OffsetToStrTbl;
277
  support::big64_t OffsetToSymTbl;
278
  support::big64_t OffsetToRelEnt;
279
 
280
  uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; }
281
  uint64_t getOffsetToRelEnt() const { return OffsetToRelEnt; }
282
};
283
 
284
template <typename AddressType> struct ExceptionSectionEntry {
285
  union {
286
    support::ubig32_t SymbolIdx;
287
    AddressType TrapInstAddr;
288
  };
289
  uint8_t LangId;
290
  uint8_t Reason;
291
 
292
  uint32_t getSymbolIndex() const {
293
    assert(Reason == 0 && "Get symbol table index of the function only when "
294
                          "the e_reason field is 0.");
295
    return SymbolIdx;
296
  }
297
 
298
  uint64_t getTrapInstAddr() const {
299
    assert(Reason != 0 && "Zero is not a valid trap exception reason code.");
300
    return TrapInstAddr;
301
  }
302
  uint8_t getLangID() const { return LangId; }
303
  uint8_t getReason() const { return Reason; }
304
};
305
 
306
typedef ExceptionSectionEntry<support::ubig32_t> ExceptionSectionEntry32;
307
typedef ExceptionSectionEntry<support::ubig64_t> ExceptionSectionEntry64;
308
 
309
// Explicit extern template declarations.
310
extern template struct ExceptionSectionEntry<support::ubig32_t>;
311
extern template struct ExceptionSectionEntry<support::ubig64_t>;
312
 
313
struct XCOFFStringTable {
314
  uint32_t Size;
315
  const char *Data;
316
};
317
 
318
struct XCOFFCsectAuxEnt32 {
319
  support::ubig32_t SectionOrLength;
320
  support::ubig32_t ParameterHashIndex;
321
  support::ubig16_t TypeChkSectNum;
322
  uint8_t SymbolAlignmentAndType;
323
  XCOFF::StorageMappingClass StorageMappingClass;
324
  support::ubig32_t StabInfoIndex;
325
  support::ubig16_t StabSectNum;
326
};
327
 
328
struct XCOFFCsectAuxEnt64 {
329
  support::ubig32_t SectionOrLengthLowByte;
330
  support::ubig32_t ParameterHashIndex;
331
  support::ubig16_t TypeChkSectNum;
332
  uint8_t SymbolAlignmentAndType;
333
  XCOFF::StorageMappingClass StorageMappingClass;
334
  support::ubig32_t SectionOrLengthHighByte;
335
  uint8_t Pad;
336
  XCOFF::SymbolAuxType AuxType;
337
};
338
 
339
class XCOFFCsectAuxRef {
340
public:
341
  static constexpr uint8_t SymbolTypeMask = 0x07;
342
  static constexpr uint8_t SymbolAlignmentMask = 0xF8;
343
  static constexpr size_t SymbolAlignmentBitOffset = 3;
344
 
345
  XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {}
346
  XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {}
347
 
348
  // For getSectionOrLength(),
349
  // If the symbol type is XTY_SD or XTY_CM, the csect length.
350
  // If the symbol type is XTY_LD, the symbol table
351
  // index of the containing csect.
352
  // If the symbol type is XTY_ER, 0.
353
  uint64_t getSectionOrLength() const {
354
    return Entry32 ? getSectionOrLength32() : getSectionOrLength64();
355
  }
356
 
357
  uint32_t getSectionOrLength32() const {
358
    assert(Entry32 && "32-bit interface called on 64-bit object file.");
359
    return Entry32->SectionOrLength;
360
  }
361
 
362
  uint64_t getSectionOrLength64() const {
363
    assert(Entry64 && "64-bit interface called on 32-bit object file.");
364
    return (static_cast<uint64_t>(Entry64->SectionOrLengthHighByte) << 32) |
365
           Entry64->SectionOrLengthLowByte;
366
  }
367
 
368
#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
369
 
370
  uint32_t getParameterHashIndex() const {
371
    return GETVALUE(ParameterHashIndex);
372
  }
373
 
374
  uint16_t getTypeChkSectNum() const { return GETVALUE(TypeChkSectNum); }
375
 
376
  XCOFF::StorageMappingClass getStorageMappingClass() const {
377
    return GETVALUE(StorageMappingClass);
378
  }
379
 
380
  uintptr_t getEntryAddress() const {
381
    return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
382
                   : reinterpret_cast<uintptr_t>(Entry64);
383
  }
384
 
385
  uint16_t getAlignmentLog2() const {
386
    return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >>
387
           SymbolAlignmentBitOffset;
388
  }
389
 
390
  uint8_t getSymbolType() const {
391
    return getSymbolAlignmentAndType() & SymbolTypeMask;
392
  }
393
 
394
  bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
395
 
396
  uint32_t getStabInfoIndex32() const {
397
    assert(Entry32 && "32-bit interface called on 64-bit object file.");
398
    return Entry32->StabInfoIndex;
399
  }
400
 
401
  uint16_t getStabSectNum32() const {
402
    assert(Entry32 && "32-bit interface called on 64-bit object file.");
403
    return Entry32->StabSectNum;
404
  }
405
 
406
  XCOFF::SymbolAuxType getAuxType64() const {
407
    assert(Entry64 && "64-bit interface called on 32-bit object file.");
408
    return Entry64->AuxType;
409
  }
410
 
411
private:
412
  uint8_t getSymbolAlignmentAndType() const {
413
    return GETVALUE(SymbolAlignmentAndType);
414
  }
415
 
416
#undef GETVALUE
417
 
418
  const XCOFFCsectAuxEnt32 *Entry32 = nullptr;
419
  const XCOFFCsectAuxEnt64 *Entry64 = nullptr;
420
};
421
 
422
struct XCOFFFileAuxEnt {
423
  typedef struct {
424
    support::big32_t Magic; // Zero indicates name in string table.
425
    support::ubig32_t Offset;
426
    char NamePad[XCOFF::FileNamePadSize];
427
  } NameInStrTblType;
428
  union {
429
    char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
430
    NameInStrTblType NameInStrTbl;
431
  };
432
  XCOFF::CFileStringType Type;
433
  uint8_t ReservedZeros[2];
434
  XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only.
435
};
436
 
437
struct XCOFFSectAuxEntForStat {
438
  support::ubig32_t SectionLength;
439
  support::ubig16_t NumberOfRelocEnt;
440
  support::ubig16_t NumberOfLineNum;
441
  uint8_t Pad[10];
442
}; // 32-bit XCOFF file only.
443
 
444
struct XCOFFFunctionAuxEnt32 {
445
  support::ubig32_t OffsetToExceptionTbl;
446
  support::ubig32_t SizeOfFunction;
447
  support::ubig32_t PtrToLineNum;
448
  support::big32_t SymIdxOfNextBeyond;
449
  uint8_t Pad[2];
450
};
451
 
452
struct XCOFFFunctionAuxEnt64 {
453
  support::ubig64_t PtrToLineNum;
454
  support::ubig32_t SizeOfFunction;
455
  support::big32_t SymIdxOfNextBeyond;
456
  uint8_t Pad;
457
  XCOFF::SymbolAuxType AuxType; // Contains _AUX_FCN; Type of auxiliary entry
458
};
459
 
460
struct XCOFFExceptionAuxEnt {
461
  support::ubig64_t OffsetToExceptionTbl;
462
  support::ubig32_t SizeOfFunction;
463
  support::big32_t SymIdxOfNextBeyond;
464
  uint8_t Pad;
465
  XCOFF::SymbolAuxType AuxType; // Contains _AUX_EXCEPT; Type of auxiliary entry
466
};
467
 
468
struct XCOFFBlockAuxEnt32 {
469
  uint8_t ReservedZeros1[2];
470
  support::ubig16_t LineNumHi;
471
  support::ubig16_t LineNumLo;
472
  uint8_t ReservedZeros2[12];
473
};
474
 
475
struct XCOFFBlockAuxEnt64 {
476
  support::ubig32_t LineNum;
477
  uint8_t Pad[13];
478
  XCOFF::SymbolAuxType AuxType; // Contains _AUX_SYM; Type of auxiliary entry
479
};
480
 
481
struct XCOFFSectAuxEntForDWARF32 {
482
  support::ubig32_t LengthOfSectionPortion;
483
  uint8_t Pad1[4];
484
  support::ubig32_t NumberOfRelocEnt;
485
  uint8_t Pad2[6];
486
};
487
 
488
struct XCOFFSectAuxEntForDWARF64 {
489
  support::ubig64_t LengthOfSectionPortion;
490
  support::ubig64_t NumberOfRelocEnt;
491
  uint8_t Pad;
492
  XCOFF::SymbolAuxType AuxType; // Contains _AUX_SECT; Type of Auxillary entry
493
};
494
 
495
template <typename AddressType> struct XCOFFRelocation {
496
public:
497
  AddressType VirtualAddress;
498
  support::ubig32_t SymbolIndex;
499
 
500
  // Packed field, see XR_* masks for details of packing.
501
  uint8_t Info;
502
 
503
  XCOFF::RelocationType Type;
504
 
505
public:
506
  bool isRelocationSigned() const;
507
  bool isFixupIndicated() const;
508
 
509
  // Returns the number of bits being relocated.
510
  uint8_t getRelocatedLength() const;
511
};
512
 
513
extern template struct XCOFFRelocation<llvm::support::ubig32_t>;
514
extern template struct XCOFFRelocation<llvm::support::ubig64_t>;
515
 
516
struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {};
517
struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {};
518
 
519
class XCOFFSymbolRef;
520
 
521
class XCOFFObjectFile : public ObjectFile {
522
private:
523
  const void *FileHeader = nullptr;
524
  const void *AuxiliaryHeader = nullptr;
525
  const void *SectionHeaderTable = nullptr;
526
 
527
  const void *SymbolTblPtr = nullptr;
528
  XCOFFStringTable StringTable = {0, nullptr};
529
 
530
  const XCOFFSectionHeader32 *sectionHeaderTable32() const;
531
  const XCOFFSectionHeader64 *sectionHeaderTable64() const;
532
  template <typename T> const T *sectionHeaderTable() const;
533
 
534
  size_t getFileHeaderSize() const;
535
  size_t getSectionHeaderSize() const;
536
 
537
  const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
538
  const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
539
  uintptr_t getSectionHeaderTableAddress() const;
540
  uintptr_t getEndOfSymbolTableAddress() const;
541
 
542
  DataRefImpl getSectionByType(XCOFF::SectionTypeFlags SectType) const;
543
  uint64_t getSectionFileOffsetToRawData(DataRefImpl Sec) const;
544
 
545
  // This returns a pointer to the start of the storage for the name field of
546
  // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
547
  // null-terminated.
548
  const char *getSectionNameInternal(DataRefImpl Sec) const;
549
 
550
  static bool isReservedSectionNumber(int16_t SectionNumber);
551
 
552
  // Constructor and "create" factory function. The constructor is only a thin
553
  // wrapper around the base constructor. The "create" function fills out the
554
  // XCOFF-specific information and performs the error checking along the way.
555
  XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
556
  static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
557
                                                           MemoryBufferRef MBR);
558
 
559
  // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
560
  // and an XCOFFStringTable if parsing succeeded.
561
  static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
562
                                                     uint64_t Offset);
563
 
564
  // Make a friend so it can call the private 'create' function.
565
  friend Expected<std::unique_ptr<ObjectFile>>
566
  ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
567
 
568
  void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
569
 
570
public:
571
  static constexpr uint64_t InvalidRelocOffset =
572
      std::numeric_limits<uint64_t>::max();
573
 
574
  // Interface inherited from base classes.
575
  void moveSymbolNext(DataRefImpl &Symb) const override;
576
  Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
577
  basic_symbol_iterator symbol_begin() const override;
578
  basic_symbol_iterator symbol_end() const override;
579
 
580
  Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
581
  Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
582
  uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
583
  uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
584
  uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
585
  Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
586
  Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
587
 
588
  void moveSectionNext(DataRefImpl &Sec) const override;
589
  Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
590
  uint64_t getSectionAddress(DataRefImpl Sec) const override;
591
  uint64_t getSectionIndex(DataRefImpl Sec) const override;
592
  uint64_t getSectionSize(DataRefImpl Sec) const override;
593
  Expected<ArrayRef<uint8_t>>
594
  getSectionContents(DataRefImpl Sec) const override;
595
  uint64_t getSectionAlignment(DataRefImpl Sec) const override;
596
  bool isSectionCompressed(DataRefImpl Sec) const override;
597
  bool isSectionText(DataRefImpl Sec) const override;
598
  bool isSectionData(DataRefImpl Sec) const override;
599
  bool isSectionBSS(DataRefImpl Sec) const override;
600
  bool isDebugSection(DataRefImpl Sec) const override;
601
 
602
  bool isSectionVirtual(DataRefImpl Sec) const override;
603
  relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
604
  relocation_iterator section_rel_end(DataRefImpl Sec) const override;
605
 
606
  void moveRelocationNext(DataRefImpl &Rel) const override;
607
 
608
  /// \returns the relocation offset with the base address of the containing
609
  /// section as zero, or InvalidRelocOffset on errors (such as a relocation
610
  /// that does not refer to an address in any section).
611
  uint64_t getRelocationOffset(DataRefImpl Rel) const override;
612
  symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
613
  uint64_t getRelocationType(DataRefImpl Rel) const override;
614
  void getRelocationTypeName(DataRefImpl Rel,
615
                             SmallVectorImpl<char> &Result) const override;
616
 
617
  section_iterator section_begin() const override;
618
  section_iterator section_end() const override;
619
  uint8_t getBytesInAddress() const override;
620
  StringRef getFileFormatName() const override;
621
  Triple::ArchType getArch() const override;
622
  Expected<SubtargetFeatures> getFeatures() const override;
623
  Expected<uint64_t> getStartAddress() const override;
624
  StringRef mapDebugSectionName(StringRef Name) const override;
625
  bool isRelocatableObject() const override;
626
 
627
  // Below here is the non-inherited interface.
628
  bool is64Bit() const;
629
  Expected<StringRef> getRawData(const char *Start, uint64_t Size,
630
                                 StringRef Name) const;
631
 
632
  const XCOFFAuxiliaryHeader32 *auxiliaryHeader32() const;
633
  const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() const;
634
 
635
  const void *getPointerToSymbolTable() const { return SymbolTblPtr; }
636
 
637
  Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const;
638
  unsigned getSymbolSectionID(SymbolRef Sym) const;
639
  XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const;
640
 
641
  // File header related interfaces.
642
  const XCOFFFileHeader32 *fileHeader32() const;
643
  const XCOFFFileHeader64 *fileHeader64() const;
644
  uint16_t getMagic() const;
645
  uint16_t getNumberOfSections() const;
646
  int32_t getTimeStamp() const;
647
 
648
  // Symbol table offset and entry count are handled differently between
649
  // XCOFF32 and XCOFF64.
650
  uint32_t getSymbolTableOffset32() const;
651
  uint64_t getSymbolTableOffset64() const;
652
 
653
  // Note that this value is signed and might return a negative value. Negative
654
  // values are reserved for future use.
655
  int32_t getRawNumberOfSymbolTableEntries32() const;
656
 
657
  // The sanitized value appropriate to use as an index into the symbol table.
658
  uint32_t getLogicalNumberOfSymbolTableEntries32() const;
659
 
660
  uint32_t getNumberOfSymbolTableEntries64() const;
661
 
662
  // Return getLogicalNumberOfSymbolTableEntries32 or
663
  // getNumberOfSymbolTableEntries64 depending on the object mode.
664
  uint32_t getNumberOfSymbolTableEntries() const;
665
 
666
  uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
667
  uint64_t getSymbolSize(DataRefImpl Symb) const;
668
  uintptr_t getSymbolByIndex(uint32_t Idx) const {
669
    return reinterpret_cast<uintptr_t>(SymbolTblPtr) +
670
           XCOFF::SymbolTableEntrySize * Idx;
671
  }
672
  uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const;
673
  Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
674
 
675
  Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
676
  uint16_t getOptionalHeaderSize() const;
677
  uint16_t getFlags() const;
678
 
679
  // Section header table related interfaces.
680
  ArrayRef<XCOFFSectionHeader32> sections32() const;
681
  ArrayRef<XCOFFSectionHeader64> sections64() const;
682
 
683
  int32_t getSectionFlags(DataRefImpl Sec) const;
684
  Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
685
 
686
  Expected<uintptr_t>
687
  getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) const;
688
 
689
  void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
690
 
691
  // Relocation-related interfaces.
692
  template <typename T>
693
  Expected<uint32_t>
694
  getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const;
695
 
696
  template <typename Shdr, typename Reloc>
697
  Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const;
698
 
699
  // Loader section related interfaces.
700
  Expected<StringRef> getImportFileTable() const;
701
 
702
  // Exception-related interface.
703
  template <typename ExceptEnt>
704
  Expected<ArrayRef<ExceptEnt>> getExceptionEntries() const;
705
 
706
  // This function returns string table entry.
707
  Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
708
 
709
  // This function returns the string table.
710
  StringRef getStringTable() const;
711
 
712
  const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const;
713
 
714
  static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
715
                                                 uint32_t Distance);
716
 
717
  static bool classof(const Binary *B) { return B->isXCOFF(); }
718
}; // XCOFFObjectFile
719
 
720
typedef struct {
721
  uint8_t LanguageId;
722
  uint8_t CpuTypeId;
723
} CFileLanguageIdAndTypeIdType;
724
 
725
struct XCOFFSymbolEntry32 {
726
  typedef struct {
727
    support::big32_t Magic; // Zero indicates name in string table.
728
    support::ubig32_t Offset;
729
  } NameInStrTblType;
730
 
731
  union {
732
    char SymbolName[XCOFF::NameSize];
733
    NameInStrTblType NameInStrTbl;
734
  };
735
 
736
  support::ubig32_t Value; // Symbol value; storage class-dependent.
737
  support::big16_t SectionNumber;
738
 
739
  union {
740
    support::ubig16_t SymbolType;
741
    CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
742
  };
743
 
744
  XCOFF::StorageClass StorageClass;
745
  uint8_t NumberOfAuxEntries;
746
};
747
 
748
struct XCOFFSymbolEntry64 {
749
  support::ubig64_t Value; // Symbol value; storage class-dependent.
750
  support::ubig32_t Offset;
751
  support::big16_t SectionNumber;
752
 
753
  union {
754
    support::ubig16_t SymbolType;
755
    CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
756
  };
757
 
758
  XCOFF::StorageClass StorageClass;
759
  uint8_t NumberOfAuxEntries;
760
};
761
 
762
class XCOFFSymbolRef {
763
public:
764
  enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
765
 
766
  XCOFFSymbolRef(DataRefImpl SymEntDataRef,
767
                 const XCOFFObjectFile *OwningObjectPtr)
768
      : OwningObjectPtr(OwningObjectPtr) {
769
    assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!");
770
    assert(SymEntDataRef.p != 0 &&
771
           "Symbol table entry pointer cannot be nullptr!");
772
 
773
    if (OwningObjectPtr->is64Bit())
774
      Entry64 = reinterpret_cast<const XCOFFSymbolEntry64 *>(SymEntDataRef.p);
775
    else
776
      Entry32 = reinterpret_cast<const XCOFFSymbolEntry32 *>(SymEntDataRef.p);
777
  }
778
 
779
  const XCOFFSymbolEntry32 *getSymbol32() { return Entry32; }
780
  const XCOFFSymbolEntry64 *getSymbol64() { return Entry64; }
781
 
782
  uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); }
783
 
784
  uint32_t getValue32() const { return Entry32->Value; }
785
 
786
  uint64_t getValue64() const { return Entry64->Value; }
787
 
788
#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
789
 
790
  int16_t getSectionNumber() const { return GETVALUE(SectionNumber); }
791
 
792
  uint16_t getSymbolType() const { return GETVALUE(SymbolType); }
793
 
794
  uint8_t getLanguageIdForCFile() const {
795
    assert(getStorageClass() == XCOFF::C_FILE &&
796
           "This interface is for C_FILE only.");
797
    return GETVALUE(CFileLanguageIdAndTypeId.LanguageId);
798
  }
799
 
800
  uint8_t getCPUTypeIddForCFile() const {
801
    assert(getStorageClass() == XCOFF::C_FILE &&
802
           "This interface is for C_FILE only.");
803
    return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId);
804
  }
805
 
806
  XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); }
807
 
808
  uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); }
809
 
810
#undef GETVALUE
811
 
812
  uintptr_t getEntryAddress() const {
813
    return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
814
                   : reinterpret_cast<uintptr_t>(Entry64);
815
  }
816
 
817
  Expected<StringRef> getName() const;
818
  bool isFunction() const;
819
  bool isCsectSymbol() const;
820
  Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const;
821
 
822
private:
823
  const XCOFFObjectFile *OwningObjectPtr;
824
  const XCOFFSymbolEntry32 *Entry32 = nullptr;
825
  const XCOFFSymbolEntry64 *Entry64 = nullptr;
826
};
827
 
828
class TBVectorExt {
829
  uint16_t Data;
830
  SmallString<32> VecParmsInfo;
831
 
832
  TBVectorExt(StringRef TBvectorStrRef, Error &Err);
833
 
834
public:
835
  static Expected<TBVectorExt> create(StringRef TBvectorStrRef);
836
  uint8_t getNumberOfVRSaved() const;
837
  bool isVRSavedOnStack() const;
838
  bool hasVarArgs() const;
839
  uint8_t getNumberOfVectorParms() const;
840
  bool hasVMXInstruction() const;
841
  SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; };
842
};
843
 
844
/// This class provides methods to extract traceback table data from a buffer.
845
/// The various accessors may reference the buffer provided via the constructor.
846
 
847
class XCOFFTracebackTable {
848
  const uint8_t *const TBPtr;
849
  std::optional<SmallString<32>> ParmsType;
850
  std::optional<uint32_t> TraceBackTableOffset;
851
  std::optional<uint32_t> HandlerMask;
852
  std::optional<uint32_t> NumOfCtlAnchors;
853
  std::optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
854
  std::optional<StringRef> FunctionName;
855
  std::optional<uint8_t> AllocaRegister;
856
  std::optional<TBVectorExt> VecExt;
857
  std::optional<uint8_t> ExtensionTable;
858
 
859
  XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
860
 
861
public:
862
  /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
863
  /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
864
  /// Error is returned.
865
  ///
866
  /// \param[in] Ptr
867
  ///   A pointer that points just past the initial 4 bytes of zeros at the
868
  ///   beginning of an XCOFF Traceback Table.
869
  ///
870
  /// \param[in, out] Size
871
  ///    A pointer that points to the length of the XCOFF Traceback Table.
872
  ///    If the XCOFF Traceback Table is not parsed successfully or there are
873
  ///    extra bytes that are not recognized, \a Size will be updated to be the
874
  ///    size up to the end of the last successfully parsed field of the table.
875
  static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
876
                                              uint64_t &Size);
877
  uint8_t getVersion() const;
878
  uint8_t getLanguageID() const;
879
 
880
  bool isGlobalLinkage() const;
881
  bool isOutOfLineEpilogOrPrologue() const;
882
  bool hasTraceBackTableOffset() const;
883
  bool isInternalProcedure() const;
884
  bool hasControlledStorage() const;
885
  bool isTOCless() const;
886
  bool isFloatingPointPresent() const;
887
  bool isFloatingPointOperationLogOrAbortEnabled() const;
888
 
889
  bool isInterruptHandler() const;
890
  bool isFuncNamePresent() const;
891
  bool isAllocaUsed() const;
892
  uint8_t getOnConditionDirective() const;
893
  bool isCRSaved() const;
894
  bool isLRSaved() const;
895
 
896
  bool isBackChainStored() const;
897
  bool isFixup() const;
898
  uint8_t getNumOfFPRsSaved() const;
899
 
900
  bool hasVectorInfo() const;
901
  bool hasExtensionTable() const;
902
  uint8_t getNumOfGPRsSaved() const;
903
 
904
  uint8_t getNumberOfFixedParms() const;
905
 
906
  uint8_t getNumberOfFPParms() const;
907
  bool hasParmsOnStack() const;
908
 
909
  const std::optional<SmallString<32>> &getParmsType() const {
910
    return ParmsType;
911
  }
912
  const std::optional<uint32_t> &getTraceBackTableOffset() const {
913
    return TraceBackTableOffset;
914
  }
915
  const std::optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
916
  const std::optional<uint32_t> &getNumOfCtlAnchors() {
917
    return NumOfCtlAnchors;
918
  }
919
  const std::optional<SmallVector<uint32_t, 8>> &
920
  getControlledStorageInfoDisp() {
921
    return ControlledStorageInfoDisp;
922
  }
923
  const std::optional<StringRef> &getFunctionName() const {
924
    return FunctionName;
925
  }
926
  const std::optional<uint8_t> &getAllocaRegister() const {
927
    return AllocaRegister;
928
  }
929
  const std::optional<TBVectorExt> &getVectorExt() const { return VecExt; }
930
  const std::optional<uint8_t> &getExtensionTable() const {
931
    return ExtensionTable;
932
  }
933
};
934
 
935
bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
936
} // namespace object
937
} // namespace llvm
938
 
939
#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H