@@ -26,6 +26,17 @@ enum { XCOFF32FileHeaderSize = 20 };
26
26
static_assert (sizeof (XCOFFFileHeader) == XCOFF32FileHeaderSize,
27
27
" Wrong size for XCOFF file header." );
28
28
29
+ // Sets EC and returns false if there is less than 'Size' bytes left in the
30
+ // buffer at 'Offset'.
31
+ static bool checkSize (MemoryBufferRef M, std::error_code &EC, uint64_t Offset,
32
+ uint64_t Size ) {
33
+ if (M.getBufferSize () < Offset + Size ) {
34
+ EC = object_error::unexpected_eof;
35
+ return false ;
36
+ }
37
+ return true ;
38
+ }
39
+
29
40
// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
30
41
// Returns unexpected_eof on error.
31
42
template <typename T>
@@ -43,6 +54,12 @@ template <typename T> static const T *viewAs(uintptr_t in) {
43
54
return reinterpret_cast <const T *>(in);
44
55
}
45
56
57
+ static StringRef generateStringRef (const char *Name, uint64_t Size ) {
58
+ auto NulCharPtr = static_cast <const char *>(memchr (Name, ' \0 ' , Size ));
59
+ return NulCharPtr ? StringRef (Name, NulCharPtr - Name)
60
+ : StringRef (Name, Size );
61
+ }
62
+
46
63
const XCOFFSectionHeader *XCOFFObjectFile::toSection (DataRefImpl Ref) const {
47
64
auto Sec = viewAs<XCOFFSectionHeader>(Ref.p );
48
65
#ifndef NDEBUG
@@ -58,6 +75,12 @@ const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
58
75
return Sec;
59
76
}
60
77
78
+ const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry (DataRefImpl Ref) const {
79
+ assert (Ref.p != 0 && " Symbol table pointer can not be nullptr!" );
80
+ auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p );
81
+ return SymEntPtr;
82
+ }
83
+
61
84
// The next 2 functions are not exactly necessary yet, but they are useful to
62
85
// abstract over the size difference between XCOFF32 and XCOFF64 structure
63
86
// definitions.
@@ -69,15 +92,40 @@ size_t XCOFFObjectFile::getSectionHeaderSize() const {
69
92
return sizeof (XCOFFSectionHeader);
70
93
}
71
94
95
+ uint16_t XCOFFObjectFile::getMagic () const { return FileHdrPtr->Magic ; }
96
+
72
97
void XCOFFObjectFile::moveSymbolNext (DataRefImpl &Symb) const {
73
- llvm_unreachable (" Not yet implemented!" );
74
- return ;
98
+ const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry (Symb);
99
+
100
+ SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1 ;
101
+ Symb.p = reinterpret_cast <uintptr_t >(SymEntPtr);
75
102
}
76
103
77
104
Expected<StringRef> XCOFFObjectFile::getSymbolName (DataRefImpl Symb) const {
78
- StringRef Result;
79
- llvm_unreachable (" Not yet implemented!" );
80
- return Result;
105
+ const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry (Symb);
106
+
107
+ if (SymEntPtr->NameInStrTbl .Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
108
+ return generateStringRef (SymEntPtr->SymbolName , XCOFF::SymbolNameSize);
109
+
110
+ // A storage class value with the high-order bit on indicates that the name is
111
+ // a symbolic debugger stabstring.
112
+ if (SymEntPtr->StorageClass & 0x80 )
113
+ return StringRef (" Unimplemented Debug Name" );
114
+
115
+ uint32_t Offset = SymEntPtr->NameInStrTbl .Offset ;
116
+ // The byte offset is relative to the start of the string table
117
+ // or .debug section. A byte offset value of 0 is a null or zero-length symbol
118
+ // name. A byte offset in the range 1 to 3 (inclusive) points into the length
119
+ // field; as a soft-error recovery mechanism, we treat such cases as having an
120
+ // offset of 0.
121
+ if (Offset < 4 )
122
+ return StringRef (nullptr , 0 );
123
+
124
+ if (StringTable.Data != nullptr && StringTable.Size > Offset)
125
+ return (StringTable.Data + Offset);
126
+
127
+ return make_error<GenericBinaryError>(" Symbol Name parse failed" ,
128
+ object_error::parse_failed);
81
129
}
82
130
83
131
Expected<uint64_t > XCOFFObjectFile::getSymbolAddress (DataRefImpl Symb) const {
@@ -87,9 +135,7 @@ Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
87
135
}
88
136
89
137
uint64_t XCOFFObjectFile::getSymbolValueImpl (DataRefImpl Symb) const {
90
- uint64_t Result = 0 ;
91
- llvm_unreachable (" Not yet implemented!" );
92
- return Result;
138
+ return toSymbolEntry (Symb)->Value ;
93
139
}
94
140
95
141
uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl (DataRefImpl Symb) const {
@@ -106,8 +152,20 @@ XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
106
152
107
153
Expected<section_iterator>
108
154
XCOFFObjectFile::getSymbolSection (DataRefImpl Symb) const {
109
- llvm_unreachable (" Not yet implemented!" );
110
- return section_iterator (SectionRef ());
155
+ const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry (Symb);
156
+ int16_t SectNum = SymEntPtr->SectionNumber ;
157
+
158
+ if (isReservedSectionNumber (SectNum))
159
+ return section_end ();
160
+
161
+ const XCOFFSectionHeader *Sec;
162
+ if (std::error_code EC = getSectionByNum (SectNum, Sec))
163
+ return errorCodeToError (EC);
164
+
165
+ DataRefImpl SecDRI;
166
+ SecDRI.p = reinterpret_cast <uintptr_t >(Sec);
167
+
168
+ return section_iterator (SectionRef (SecDRI, this ));
111
169
}
112
170
113
171
void XCOFFObjectFile::moveSectionNext (DataRefImpl &Sec) const {
@@ -219,13 +277,16 @@ uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
219
277
}
220
278
221
279
basic_symbol_iterator XCOFFObjectFile::symbol_begin () const {
222
- llvm_unreachable (" Not yet implemented!" );
223
- return basic_symbol_iterator (SymbolRef ());
280
+ DataRefImpl SymDRI;
281
+ SymDRI.p = reinterpret_cast <uintptr_t >(SymbolTblPtr);
282
+ return basic_symbol_iterator (SymbolRef (SymDRI, this ));
224
283
}
225
284
226
285
basic_symbol_iterator XCOFFObjectFile::symbol_end () const {
227
- llvm_unreachable (" Not yet implemented!" );
228
- return basic_symbol_iterator (SymbolRef ());
286
+ DataRefImpl SymDRI;
287
+ SymDRI.p = reinterpret_cast <uintptr_t >(
288
+ SymbolTblPtr + getLogicalNumberOfSymbolTableEntries ());
289
+ return basic_symbol_iterator (SymbolRef (SymDRI, this ));
229
290
}
230
291
231
292
section_iterator XCOFFObjectFile::section_begin () const {
@@ -243,7 +304,7 @@ section_iterator XCOFFObjectFile::section_end() const {
243
304
244
305
uint8_t XCOFFObjectFile::getBytesInAddress () const {
245
306
// Only support 32-bit object files for now ...
246
- assert (getFileHeaderSize () == XCOFF32FileHeaderSize);
307
+ assert (getFileHeaderSize () == XCOFF32FileHeaderSize);
247
308
return 4 ;
248
309
}
249
310
@@ -274,6 +335,67 @@ Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
274
335
return 0 ;
275
336
}
276
337
338
+ std::error_code
339
+ XCOFFObjectFile::getSectionByNum (int16_t Num,
340
+ const XCOFFSectionHeader *&Result) const {
341
+ if (Num > 0 && static_cast <uint16_t >(Num) <= getNumberOfSections ()) {
342
+ Result = SectionHdrTablePtr + (Num - 1 );
343
+ return std::error_code ();
344
+ }
345
+
346
+ return object_error::invalid_section_index;
347
+ }
348
+
349
+ Expected<StringRef>
350
+ XCOFFObjectFile::getSymbolSectionName (const XCOFFSymbolEntry *SymEntPtr) const {
351
+ int16_t SectionNum = SymEntPtr->SectionNumber ;
352
+
353
+ switch (SectionNum) {
354
+ case XCOFF::N_DEBUG:
355
+ return " N_DEBUG" ;
356
+ case XCOFF::N_ABS:
357
+ return " N_ABS" ;
358
+ case XCOFF::N_UNDEF:
359
+ return " N_UNDEF" ;
360
+ default : {
361
+ const XCOFFSectionHeader *SectHeaderPtr;
362
+ std::error_code EC;
363
+ if ((EC = getSectionByNum (SectionNum, SectHeaderPtr)))
364
+ return errorCodeToError (EC);
365
+ else
366
+ return generateStringRef (SectHeaderPtr->Name , XCOFF::SectionNameSize);
367
+ }
368
+ }
369
+ }
370
+
371
+ bool XCOFFObjectFile::isReservedSectionNumber (int16_t SectionNumber) {
372
+ return (SectionNumber <= 0 && SectionNumber >= -2 );
373
+ }
374
+
375
+ uint16_t XCOFFObjectFile::getNumberOfSections () const {
376
+ return FileHdrPtr->NumberOfSections ;
377
+ }
378
+
379
+ int32_t XCOFFObjectFile::getTimeStamp () const { return FileHdrPtr->TimeStamp ; }
380
+
381
+ uint32_t XCOFFObjectFile::getSymbolTableOffset () const {
382
+ return FileHdrPtr->SymbolTableOffset ;
383
+ }
384
+
385
+ int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries () const {
386
+ return FileHdrPtr->NumberOfSymTableEntries ;
387
+ }
388
+
389
+ uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries () const {
390
+ return (FileHdrPtr->NumberOfSymTableEntries >= 0
391
+ ? FileHdrPtr->NumberOfSymTableEntries
392
+ : 0 );
393
+ }
394
+
395
+ uint16_t XCOFFObjectFile::getOptionalHeaderSize () const {
396
+ return FileHdrPtr->AuxHeaderSize ;
397
+ }
398
+
277
399
XCOFFObjectFile::XCOFFObjectFile (MemoryBufferRef Object, std::error_code &EC)
278
400
: ObjectFile(Binary::ID_XCOFF32, Object) {
279
401
@@ -293,37 +415,39 @@ XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
293
415
getNumberOfSections () * getSectionHeaderSize ())))
294
416
return ;
295
417
}
296
- }
297
418
298
- uint16_t XCOFFObjectFile::getMagic () const {
299
- return FileHdrPtr->Magic ;
300
- }
419
+ if (getLogicalNumberOfSymbolTableEntries () == 0 )
420
+ return ;
301
421
302
- uint16_t XCOFFObjectFile::getNumberOfSections () const {
303
- return FileHdrPtr->NumberOfSections ;
304
- }
422
+ // Get pointer to the symbol table.
423
+ CurPtr = FileHdrPtr->SymbolTableOffset ;
424
+ uint64_t SymbolTableSize = (uint64_t )(sizeof (XCOFFSymbolEntry)) *
425
+ getLogicalNumberOfSymbolTableEntries ();
305
426
306
- int32_t XCOFFObjectFile::getTimeStamp () const {
307
- return FileHdrPtr->TimeStamp ;
308
- }
427
+ if ((EC = getObject (SymbolTblPtr, Data, base () + CurPtr, SymbolTableSize)))
428
+ return ;
309
429
310
- uint32_t XCOFFObjectFile::getSymbolTableOffset () const {
311
- return FileHdrPtr->SymbolTableOffset ;
312
- }
430
+ // Move pointer to the string table.
431
+ CurPtr += SymbolTableSize;
313
432
314
- int32_t XCOFFObjectFile::getNumberOfSymbolTableEntries () const {
315
- // As far as symbol table size is concerned, if this field is negative it is
316
- // to be treated as a 0. However since this field is also used for printing we
317
- // don't want to truncate any negative values.
318
- return FileHdrPtr->NumberOfSymTableEntries ;
319
- }
433
+ if (CurPtr + 4 > Data.getBufferSize ())
434
+ return ;
320
435
321
- uint16_t XCOFFObjectFile::getOptionalHeaderSize () const {
322
- return FileHdrPtr->AuxHeaderSize ;
323
- }
436
+ StringTable.Size = support::endian::read32be (base () + CurPtr);
437
+
438
+ if (StringTable.Size <= 4 )
439
+ return ;
440
+
441
+ // Check for whether the String table has the size indicated by length
442
+ // field
443
+ if (!checkSize (Data, EC, CurPtr, StringTable.Size ))
444
+ return ;
324
445
325
- uint16_t XCOFFObjectFile::getFlags () const {
326
- return FileHdrPtr->Flags ;
446
+ StringTable.Data = reinterpret_cast <const char *>(base () + CurPtr);
447
+ if (StringTable.Data [StringTable.Size - 1 ] != ' \0 ' ) {
448
+ EC = object_error::string_table_non_null_end;
449
+ return ;
450
+ }
327
451
}
328
452
329
453
Expected<std::unique_ptr<ObjectFile>>
0 commit comments