Skip to content

Commit 9212206

Browse files
committedMay 28, 2019
[XCOFF] Implement parsing symbol table for xcoffobjfile and output as yaml format
Summary: This patch implement parsing symbol table for xcoffobjfile and output as yaml format. Parsing auxiliary entries of a symbol will be in a separate patch. The XCOFF object file (aix_xcoff.o) used in the test comes from -bash-4.2$ cat test.c extern int i; extern int TestforXcoff; int main() { i++; TestforXcoff--; } Patch by DiggerLin Reviewers: sfertile, hubert.reinterpretcast, MaskRay, daltenty Differential Revision: https://reviews.llvm.org/D61532 llvm-svn: 361832
1 parent 71f8f74 commit 9212206

File tree

9 files changed

+500
-59
lines changed

9 files changed

+500
-59
lines changed
 

‎llvm/include/llvm/BinaryFormat/XCOFF.h

+73-1
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
#ifndef LLVM_BINARYFORMAT_XCOFF_H
1414
#define LLVM_BINARYFORMAT_XCOFF_H
1515

16+
#include <cstdint>
17+
1618
namespace llvm {
1719
namespace XCOFF {
1820

1921
// Constants used in the XCOFF definition.
20-
enum { SectionNameSize = 8 };
22+
enum { SectionNameSize = 8, SymbolNameSize = 8 };
23+
enum ReservedSectionNum { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 };
2124

2225
// Flags for defining the section type. Used for the s_flags field of
2326
// the section header structure. Defined in the system header `scnhdr.h`.
@@ -37,6 +40,75 @@ enum SectionTypeFlags {
3740
STYP_OVRFLO = 0x8000
3841
};
3942

43+
// STORAGE CLASSES, n_sclass field of syment.
44+
// The values come from `storclass.h` and `dbxstclass.h`.
45+
enum StorageClass : uint8_t {
46+
// Storage classes used for symbolic debugging symbols.
47+
C_FILE = 103, // File name
48+
C_BINCL = 108, // Beginning of include file
49+
C_EINCL = 109, // Ending of include file
50+
C_GSYM = 128, // Global variable
51+
C_STSYM = 133, // Statically allocated symbol
52+
C_BCOMM = 135, // Beginning of common block
53+
C_ECOMM = 137, // End of common block
54+
C_ENTRY = 141, // Alternate entry
55+
C_BSTAT = 143, // Beginning of static block
56+
C_ESTAT = 144, // End of static block
57+
C_GTLS = 145, // Global thread-local variable
58+
C_STTLS = 146, // Static thread-local variable
59+
60+
// Storage classes used for DWARF symbols.
61+
C_DWARF = 112, // DWARF section symbol
62+
63+
// Storage classes used for absolute symbols.
64+
C_LSYM = 129, // Automatic variable allocated on stack
65+
C_PSYM = 130, // Argument to subroutine allocated on stack
66+
C_RSYM = 131, // Register variable
67+
C_RPSYM = 132, // Argument to function or procedure stored in register
68+
C_ECOML = 136, // Local member of common block
69+
C_FUN = 142, // Function or procedure
70+
71+
// Storage classes used for undefined external symbols or
72+
// symbols of general sections.
73+
C_EXT = 2, // External symbol
74+
C_WEAKEXT = 111, // Weak external symbol
75+
76+
// Storage classes used for symbols of general sections.
77+
C_NULL = 0,
78+
C_STAT = 3, // Static
79+
C_BLOCK = 100, // ".bb" or ".eb"
80+
C_FCN = 101, // ".bf" or ".ef"
81+
C_HIDEXT = 107, // Un-named external symbol
82+
C_INFO = 110, // Comment string in .info section
83+
C_DECL = 140, // Declaration of object (type)
84+
85+
// Storage classes - Obsolete/Undocumented.
86+
C_AUTO = 1, // Automatic variable
87+
C_REG = 4, // Register variable
88+
C_EXTDEF = 5, // External definition
89+
C_LABEL = 6, // Label
90+
C_ULABEL = 7, // Undefined label
91+
C_MOS = 8, // Member of structure
92+
C_ARG = 9, // Function argument
93+
C_STRTAG = 10, // Structure tag
94+
C_MOU = 11, // Member of union
95+
C_UNTAG = 12, // Union tag
96+
C_TPDEF = 13, // Type definition
97+
C_USTATIC = 14, // Undefined static
98+
C_ENTAG = 15, // Enumeration tag
99+
C_MOE = 16, // Member of enumeration
100+
C_REGPARM = 17, // Register parameter
101+
C_FIELD = 18, // Bit field
102+
C_EOS = 102, // End of structure
103+
C_LINE = 104,
104+
C_ALIAS = 105, // Duplicate tag
105+
C_HIDDEN = 106, // Special storage class for external
106+
C_EFCN = 255, // Physical end of function
107+
108+
// Storage classes - reserved
109+
C_TCSYM = 134 // Reserved
110+
};
111+
40112
} // end namespace XCOFF
41113
} // end namespace llvm
42114

‎llvm/include/llvm/Object/XCOFFObjectFile.h

+54-7
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,54 @@ struct XCOFFSectionHeader {
6161
support::big32_t Flags;
6262
};
6363

64+
struct XCOFFSymbolEntry {
65+
enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
66+
typedef struct {
67+
support::big32_t Magic; // Zero indicates name in string table.
68+
support::ubig32_t Offset;
69+
} NameInStrTblType;
70+
71+
typedef struct {
72+
uint8_t LanguageId;
73+
uint8_t CpuTypeId;
74+
} CFileLanguageIdAndTypeIdType;
75+
76+
union {
77+
char SymbolName[XCOFF::SymbolNameSize];
78+
NameInStrTblType NameInStrTbl;
79+
};
80+
81+
support::ubig32_t Value; // Symbol value; storage class-dependent.
82+
support::big16_t SectionNumber;
83+
84+
union {
85+
support::ubig16_t SymbolType;
86+
CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
87+
};
88+
89+
XCOFF::StorageClass StorageClass;
90+
uint8_t NumberOfAuxEntries;
91+
};
92+
93+
struct XCOFFStringTable {
94+
uint32_t Size;
95+
const char *Data;
96+
};
97+
6498
class XCOFFObjectFile : public ObjectFile {
6599
private:
66100
const XCOFFFileHeader *FileHdrPtr = nullptr;
67101
const XCOFFSectionHeader *SectionHdrTablePtr = nullptr;
102+
const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
103+
XCOFFStringTable StringTable = {0, nullptr};
68104

69105
size_t getFileHeaderSize() const;
70106
size_t getSectionHeaderSize() const;
71107

72108
const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
73-
109+
static bool isReservedSectionNumber(int16_t SectionNumber);
110+
std::error_code getSectionByNum(int16_t Num,
111+
const XCOFFSectionHeader *&Result) const;
74112

75113
public:
76114
void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -121,18 +159,27 @@ class XCOFFObjectFile : public ObjectFile {
121159
XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
122160

123161
const XCOFFFileHeader *getFileHeader() const { return FileHdrPtr; }
162+
const XCOFFSymbolEntry *getPointerToSymbolTable() const {
163+
return SymbolTblPtr;
164+
}
165+
166+
Expected<StringRef>
167+
getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
124168

169+
const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
125170
uint16_t getMagic() const;
126171
uint16_t getNumberOfSections() const;
127-
int32_t getTimeStamp() const;
128-
uint32_t getSymbolTableOffset() const;
172+
int32_t getTimeStamp() const;
173+
uint32_t getSymbolTableOffset() const;
129174

130-
// Note that this value is signed and might return a negative value. Negative
131-
// values are reserved for future use.
132-
int32_t getNumberOfSymbolTableEntries() const;
175+
// Returns the value as encoded in the object file.
176+
// Negative values are reserved for future use.
177+
int32_t getRawNumberOfSymbolTableEntries() const;
133178

179+
// Returns a sanitized value, useable as an index into the symbol table.
180+
uint32_t getLogicalNumberOfSymbolTableEntries() const;
134181
uint16_t getOptionalHeaderSize() const;
135-
uint16_t getFlags() const;
182+
uint16_t getFlags() const { return FileHdrPtr->Flags; };
136183
}; // XCOFFObjectFile
137184

138185
} // namespace object

‎llvm/include/llvm/ObjectYAML/XCOFFYAML.h

+23-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
#ifndef LLVM_OBJECTYAML_XCOFFYAML_H
1313
#define LLVM_OBJECTYAML_XCOFFYAML_H
1414

15+
#include "llvm/BinaryFormat/XCOFF.h"
1516
#include "llvm/ObjectYAML/YAML.h"
16-
#include <cstdint>
17+
#include <vector>
1718

1819
namespace llvm {
1920
namespace XCOFFYAML {
@@ -28,14 +29,30 @@ struct FileHeader {
2829
llvm::yaml::Hex16 Flags;
2930
};
3031

32+
struct Symbol {
33+
StringRef SymbolName;
34+
llvm::yaml::Hex32 Value; // Symbol value; storage class-dependent.
35+
StringRef SectionName;
36+
llvm::yaml::Hex16 Type;
37+
XCOFF::StorageClass StorageClass;
38+
uint8_t NumberOfAuxEntries; // Number of auxiliary entries
39+
};
40+
3141
struct Object {
3242
FileHeader Header;
43+
std::vector<Symbol> Symbols;
3344
Object();
3445
};
3546
} // namespace XCOFFYAML
36-
47+
} // namespace llvm
48+
LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Symbol)
49+
namespace llvm {
3750
namespace yaml {
3851

52+
template <> struct ScalarEnumerationTraits<XCOFF::StorageClass> {
53+
static void enumeration(IO &IO, XCOFF::StorageClass &Value);
54+
};
55+
3956
template <> struct MappingTraits<XCOFFYAML::FileHeader> {
4057
static void mapping(IO &IO, XCOFFYAML::FileHeader &H);
4158
};
@@ -44,6 +61,10 @@ template <> struct MappingTraits<XCOFFYAML::Object> {
4461
static void mapping(IO &IO, XCOFFYAML::Object &Obj);
4562
};
4663

64+
template <> struct MappingTraits<XCOFFYAML::Symbol> {
65+
static void mapping(IO &IO, XCOFFYAML::Symbol &S);
66+
};
67+
4768
} // namespace yaml
4869
} // namespace llvm
4970

‎llvm/lib/Object/XCOFFObjectFile.cpp

+163-39
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ enum { XCOFF32FileHeaderSize = 20 };
2626
static_assert(sizeof(XCOFFFileHeader) == XCOFF32FileHeaderSize,
2727
"Wrong size for XCOFF file header.");
2828

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+
2940
// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
3041
// Returns unexpected_eof on error.
3142
template <typename T>
@@ -43,6 +54,12 @@ template <typename T> static const T *viewAs(uintptr_t in) {
4354
return reinterpret_cast<const T *>(in);
4455
}
4556

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+
4663
const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
4764
auto Sec = viewAs<XCOFFSectionHeader>(Ref.p);
4865
#ifndef NDEBUG
@@ -58,6 +75,12 @@ const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
5875
return Sec;
5976
}
6077

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+
6184
// The next 2 functions are not exactly necessary yet, but they are useful to
6285
// abstract over the size difference between XCOFF32 and XCOFF64 structure
6386
// definitions.
@@ -69,15 +92,40 @@ size_t XCOFFObjectFile::getSectionHeaderSize() const {
6992
return sizeof(XCOFFSectionHeader);
7093
}
7194

95+
uint16_t XCOFFObjectFile::getMagic() const { return FileHdrPtr->Magic; }
96+
7297
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);
75102
}
76103

77104
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);
81129
}
82130

83131
Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
@@ -87,9 +135,7 @@ Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
87135
}
88136

89137
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;
93139
}
94140

95141
uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
@@ -106,8 +152,20 @@ XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
106152

107153
Expected<section_iterator>
108154
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));
111169
}
112170

113171
void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
@@ -219,13 +277,16 @@ uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
219277
}
220278

221279
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));
224283
}
225284

226285
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));
229290
}
230291

231292
section_iterator XCOFFObjectFile::section_begin() const {
@@ -243,7 +304,7 @@ section_iterator XCOFFObjectFile::section_end() const {
243304

244305
uint8_t XCOFFObjectFile::getBytesInAddress() const {
245306
// Only support 32-bit object files for now ...
246-
assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
307+
assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
247308
return 4;
248309
}
249310

@@ -274,6 +335,67 @@ Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
274335
return 0;
275336
}
276337

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+
277399
XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
278400
: ObjectFile(Binary::ID_XCOFF32, Object) {
279401

@@ -293,37 +415,39 @@ XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
293415
getNumberOfSections() * getSectionHeaderSize())))
294416
return;
295417
}
296-
}
297418

298-
uint16_t XCOFFObjectFile::getMagic() const {
299-
return FileHdrPtr->Magic;
300-
}
419+
if (getLogicalNumberOfSymbolTableEntries() == 0)
420+
return;
301421

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();
305426

306-
int32_t XCOFFObjectFile::getTimeStamp() const {
307-
return FileHdrPtr->TimeStamp;
308-
}
427+
if ((EC = getObject(SymbolTblPtr, Data, base() + CurPtr, SymbolTableSize)))
428+
return;
309429

310-
uint32_t XCOFFObjectFile::getSymbolTableOffset() const {
311-
return FileHdrPtr->SymbolTableOffset;
312-
}
430+
// Move pointer to the string table.
431+
CurPtr += SymbolTableSize;
313432

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;
320435

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;
324445

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+
}
327451
}
328452

329453
Expected<std::unique_ptr<ObjectFile>>

‎llvm/lib/ObjectYAML/XCOFFYAML.cpp

+67
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "llvm/ObjectYAML/XCOFFYAML.h"
14+
#include "llvm/BinaryFormat/XCOFF.h"
1415
#include <string.h>
1516

1617
namespace llvm {
@@ -22,6 +23,62 @@ Object::Object() { memset(&Header, 0, sizeof(Header)); }
2223

2324
namespace yaml {
2425

26+
void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
27+
IO &IO, XCOFF::StorageClass &Value) {
28+
#define ECase(X) IO.enumCase(Value, #X, XCOFF::X)
29+
ECase(C_NULL);
30+
ECase(C_AUTO);
31+
ECase(C_EXT);
32+
ECase(C_STAT);
33+
ECase(C_REG);
34+
ECase(C_EXTDEF);
35+
ECase(C_LABEL);
36+
ECase(C_ULABEL);
37+
ECase(C_MOS);
38+
ECase(C_ARG);
39+
ECase(C_STRTAG);
40+
ECase(C_MOU);
41+
ECase(C_UNTAG);
42+
ECase(C_TPDEF);
43+
ECase(C_USTATIC);
44+
ECase(C_ENTAG);
45+
ECase(C_MOE);
46+
ECase(C_REGPARM);
47+
ECase(C_FIELD);
48+
ECase(C_BLOCK);
49+
ECase(C_FCN);
50+
ECase(C_EOS);
51+
ECase(C_FILE);
52+
ECase(C_LINE);
53+
ECase(C_ALIAS);
54+
ECase(C_HIDDEN);
55+
ECase(C_HIDEXT);
56+
ECase(C_BINCL);
57+
ECase(C_EINCL);
58+
ECase(C_INFO);
59+
ECase(C_WEAKEXT);
60+
ECase(C_DWARF);
61+
ECase(C_GSYM);
62+
ECase(C_LSYM);
63+
ECase(C_PSYM);
64+
ECase(C_RSYM);
65+
ECase(C_RPSYM);
66+
ECase(C_STSYM);
67+
ECase(C_TCSYM);
68+
ECase(C_BCOMM);
69+
ECase(C_ECOML);
70+
ECase(C_ECOMM);
71+
ECase(C_DECL);
72+
ECase(C_ENTRY);
73+
ECase(C_FUN);
74+
ECase(C_BSTAT);
75+
ECase(C_ESTAT);
76+
ECase(C_GTLS);
77+
ECase(C_STTLS);
78+
ECase(C_EFCN);
79+
#undef ECase
80+
}
81+
2582
void MappingTraits<XCOFFYAML::FileHeader>::mapping(
2683
IO &IO, XCOFFYAML::FileHeader &FileHdr) {
2784
IO.mapRequired("MagicNumber", FileHdr.Magic);
@@ -33,9 +90,19 @@ void MappingTraits<XCOFFYAML::FileHeader>::mapping(
3390
IO.mapRequired("Flags", FileHdr.Flags);
3491
}
3592

93+
void MappingTraits<XCOFFYAML::Symbol>::mapping(IO &IO, XCOFFYAML::Symbol &S) {
94+
IO.mapRequired("Name", S.SymbolName);
95+
IO.mapRequired("Value", S.Value);
96+
IO.mapRequired("Section", S.SectionName);
97+
IO.mapRequired("Type", S.Type);
98+
IO.mapRequired("StorageClass", S.StorageClass);
99+
IO.mapRequired("NumberOfAuxEntries", S.NumberOfAuxEntries);
100+
}
101+
36102
void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) {
37103
IO.mapTag("!XCOFF", true);
38104
IO.mapRequired("FileHeader", Obj.Header);
105+
IO.mapRequired("Symbols", Obj.Symbols);
39106
}
40107

41108
} // namespace yaml
152 Bytes
Binary file not shown.

‎llvm/test/tools/obj2yaml/aix_xcoff.test

+76-7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,79 @@
22
# Test that we can parse the XCOFF object file correctly.
33
# CHECK: --- !XCOFF
44
# CHECK-NEXT: FileHeader:
5-
# CHECK-NEXT: MagicNumber: 0x01DF
6-
# CHECK-NEXT: NumberOfSections: 2
7-
# CHECK-NEXT: CreationTime: 1548692020
8-
# CHECK-NEXT: OffsetToSymbolTable: 0x00000108
9-
# CHECK-NEXT: EntriesInSymbolTable: 18
10-
# CHECK-NEXT: AuxiliaryHeaderSize: 0
11-
# CHECK-NEXT: Flags: 0x0000
5+
# CHECK-NEXT: MagicNumber: 0x01DF
6+
# CHECK-NEXT: NumberOfSections: 2
7+
# CHECK-NEXT: CreationTime: 1552337792
8+
# CHECK-NEXT: OffsetToSymbolTable: 0x0000013A
9+
# CHECK-NEXT: EntriesInSymbolTable: 22
10+
# CHECK-NEXT: AuxiliaryHeaderSize: 0
11+
# CHECK-NEXT: Flags: 0x0000
12+
13+
# CHECK: Symbols:
14+
# CHECK-NEXT: - Name: .file
15+
# CHECK-NEXT: Value: 0x00000000
16+
# CHECK-NEXT: Section: N_DEBUG
17+
# CHECK-NEXT: Type: 0x0003
18+
# CHECK-NEXT: StorageClass: C_FILE
19+
# CHECK-NEXT: NumberOfAuxEntries: 1
20+
# CHECK-NEXT: - Name: i
21+
# CHECK-NEXT: Value: 0x00000000
22+
# CHECK-NEXT: Section: N_UNDEF
23+
# CHECK-NEXT: Type: 0x0000
24+
# CHECK-NEXT: StorageClass: C_EXT
25+
# CHECK-NEXT: NumberOfAuxEntries: 1
26+
# CHECK-NEXT: - Name: TestforXcoff
27+
# CHECK-NEXT: Value: 0x00000000
28+
# CHECK-NEXT: Section: N_UNDEF
29+
# CHECK-NEXT: Type: 0x0000
30+
# CHECK-NEXT: StorageClass: C_EXT
31+
# CHECK-NEXT: NumberOfAuxEntries: 1
32+
# CHECK-NEXT: - Name: .text
33+
# CHECK-NEXT: Value: 0x00000000
34+
# CHECK-NEXT: Section: .text
35+
# CHECK-NEXT: Type: 0x0000
36+
# CHECK-NEXT: StorageClass: C_HIDEXT
37+
# CHECK-NEXT: NumberOfAuxEntries: 1
38+
# CHECK-NEXT: - Name: .main
39+
# CHECK-NEXT: Value: 0x00000000
40+
# CHECK-NEXT: Section: .text
41+
# CHECK-NEXT: Type: 0x0000
42+
# CHECK-NEXT: StorageClass: C_EXT
43+
# CHECK-NEXT: NumberOfAuxEntries: 1
44+
# CHECK-NEXT: - Name: main
45+
# CHECK-NEXT: Value: 0x00000060
46+
# CHECK-NEXT: Section: .data
47+
# CHECK-NEXT: Type: 0x0000
48+
# CHECK-NEXT: StorageClass: C_HIDEXT
49+
# CHECK-NEXT: NumberOfAuxEntries: 1
50+
# CHECK-NEXT: - Name: main
51+
# CHECK-NEXT: Value: 0x00000060
52+
# CHECK-NEXT: Section: .data
53+
# CHECK-NEXT: Type: 0x0000
54+
# CHECK-NEXT: StorageClass: C_EXT
55+
# CHECK-NEXT: NumberOfAuxEntries: 1
56+
# CHECK-NEXT: - Name: .data
57+
# CHECK-NEXT: Value: 0x00000070
58+
# CHECK-NEXT: Section: .data
59+
# CHECK-NEXT: Type: 0x0000
60+
# CHECK-NEXT: StorageClass: C_HIDEXT
61+
# CHECK-NEXT: NumberOfAuxEntries: 1
62+
# CHECK-NEXT: - Name: TOC
63+
# CHECK-NEXT: Value: 0x00000074
64+
# CHECK-NEXT: Section: .data
65+
# CHECK-NEXT: Type: 0x0000
66+
# CHECK-NEXT: StorageClass: C_HIDEXT
67+
# CHECK-NEXT: NumberOfAuxEntries: 1
68+
# CHECK-NEXT: - Name: i
69+
# CHECK-NEXT: Value: 0x00000074
70+
# CHECK-NEXT: Section: .data
71+
# CHECK-NEXT: Type: 0x0000
72+
# CHECK-NEXT: StorageClass: C_HIDEXT
73+
# CHECK-NEXT: NumberOfAuxEntries: 1
74+
# CHECK-NEXT: - Name: TestforXcoff
75+
# CHECK-NEXT: Value: 0x00000078
76+
# CHECK-NEXT: Section: .data
77+
# CHECK-NEXT: Type: 0x0000
78+
# CHECK-NEXT: StorageClass: C_HIDEXT
79+
# CHECK-NEXT: NumberOfAuxEntries: 1
80+
# CHECK-NEXT: ...

‎llvm/tools/llvm-readobj/XCOFFDumper.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void XCOFFDumper::printFileHeaders() {
6666
}
6767

6868
W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset());
69-
int32_t SymTabEntries = Obj.getNumberOfSymbolTableEntries();
69+
int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries();
7070
if (SymTabEntries >= 0)
7171
W.printNumber("SymbolTableEntries", SymTabEntries);
7272
else

‎llvm/tools/obj2yaml/xcoff2yaml.cpp

+43-2
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,20 @@ class XCOFFDumper {
1919
const object::XCOFFObjectFile &Obj;
2020
XCOFFYAML::Object YAMLObj;
2121
void dumpHeader();
22+
std::error_code dumpSymbols();
2223

2324
public:
24-
XCOFFDumper(const object::XCOFFObjectFile &obj);
25+
XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {}
26+
std::error_code dump();
2527
XCOFFYAML::Object &getYAMLObj() { return YAMLObj; }
2628
};
2729
} // namespace
2830

29-
XCOFFDumper::XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {
31+
std::error_code XCOFFDumper::dump() {
32+
std::error_code EC;
3033
dumpHeader();
34+
EC = dumpSymbols();
35+
return EC;
3136
}
3237

3338
void XCOFFDumper::dumpHeader() {
@@ -42,9 +47,45 @@ void XCOFFDumper::dumpHeader() {
4247
YAMLObj.Header.Flags = FileHdrPtr->Flags;
4348
}
4449

50+
std::error_code XCOFFDumper::dumpSymbols() {
51+
std::vector<XCOFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
52+
53+
for (const SymbolRef &S : Obj.symbols()) {
54+
DataRefImpl SymbolDRI = S.getRawDataRefImpl();
55+
const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
56+
XCOFFYAML::Symbol Sym;
57+
58+
Expected<StringRef> SymNameRefOrErr = Obj.getSymbolName(SymbolDRI);
59+
if (!SymNameRefOrErr) {
60+
return errorToErrorCode(SymNameRefOrErr.takeError());
61+
}
62+
Sym.SymbolName = SymNameRefOrErr.get();
63+
64+
Sym.Value = SymbolEntPtr->Value;
65+
66+
Expected<StringRef> SectionNameRefOrErr =
67+
Obj.getSymbolSectionName(SymbolEntPtr);
68+
if (!SectionNameRefOrErr)
69+
return errorToErrorCode(SectionNameRefOrErr.takeError());
70+
71+
Sym.SectionName = SectionNameRefOrErr.get();
72+
73+
Sym.Type = SymbolEntPtr->SymbolType;
74+
Sym.StorageClass = SymbolEntPtr->StorageClass;
75+
Sym.NumberOfAuxEntries = SymbolEntPtr->NumberOfAuxEntries;
76+
Symbols.push_back(Sym);
77+
}
78+
79+
return std::error_code();
80+
}
81+
4582
std::error_code xcoff2yaml(raw_ostream &Out,
4683
const object::XCOFFObjectFile &Obj) {
4784
XCOFFDumper Dumper(Obj);
85+
86+
if (std::error_code EC = Dumper.dump())
87+
return EC;
88+
4889
yaml::Output Yout(Out);
4990
Yout << Dumper.getYAMLObj();
5091

0 commit comments

Comments
 (0)
Please sign in to comment.