Skip to content

Commit 8179364

Browse files
author
Esme-Yi
committed
[yaml2obj][XCOFF] parsing auxiliary symbols.
Summary: The patch adds support for yaml2obj parsing auxiliary symbols for XCOFF. Since the test cases of this patch are interdependent with D113825 ([llvm-readobj][XCOFF] dump auxiliary symbols), test cases of this patch will be committed after D113825 is committed. Reviewed By: jhenderson, DiggerLin Differential Revision: https://reviews.llvm.org/D113552
1 parent 2c46ca9 commit 8179364

File tree

4 files changed

+456
-15
lines changed

4 files changed

+456
-15
lines changed

llvm/include/llvm/ObjectYAML/XCOFFYAML.h

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,119 @@ struct Section {
8282
std::vector<Relocation> Relocations;
8383
};
8484

85+
enum AuxSymbolType : uint8_t {
86+
AUX_EXCEPT = 255,
87+
AUX_FCN = 254,
88+
AUX_SYM = 253,
89+
AUX_FILE = 252,
90+
AUX_CSECT = 251,
91+
AUX_SECT = 250,
92+
AUX_STAT = 249
93+
};
94+
95+
struct AuxSymbolEnt {
96+
AuxSymbolType Type;
97+
98+
explicit AuxSymbolEnt(AuxSymbolType T) : Type(T) {}
99+
virtual ~AuxSymbolEnt();
100+
};
101+
102+
struct FileAuxEnt : AuxSymbolEnt {
103+
Optional<StringRef> FileNameOrString;
104+
Optional<XCOFF::CFileStringType> FileStringType;
105+
106+
FileAuxEnt() : AuxSymbolEnt(AuxSymbolType::AUX_FILE) {}
107+
static bool classof(const AuxSymbolEnt *S) {
108+
return S->Type == AuxSymbolType::AUX_FILE;
109+
}
110+
};
111+
112+
struct CsectAuxEnt : AuxSymbolEnt {
113+
// Only for XCOFF32.
114+
Optional<uint32_t> SectionOrLength;
115+
Optional<uint32_t> StabInfoIndex;
116+
Optional<uint16_t> StabSectNum;
117+
// Only for XCOFF64.
118+
Optional<uint32_t> SectionOrLengthLo;
119+
Optional<uint32_t> SectionOrLengthHi;
120+
// Common fields for both XCOFF32 and XCOFF64.
121+
Optional<uint32_t> ParameterHashIndex;
122+
Optional<uint16_t> TypeChkSectNum;
123+
Optional<uint8_t> SymbolAlignmentAndType;
124+
Optional<XCOFF::StorageMappingClass> StorageMappingClass;
125+
126+
CsectAuxEnt() : AuxSymbolEnt(AuxSymbolType::AUX_CSECT) {}
127+
static bool classof(const AuxSymbolEnt *S) {
128+
return S->Type == AuxSymbolType::AUX_CSECT;
129+
}
130+
};
131+
132+
struct FunctionAuxEnt : AuxSymbolEnt {
133+
Optional<uint32_t> OffsetToExceptionTbl; // Only for XCOFF32.
134+
Optional<uint64_t> PtrToLineNum;
135+
Optional<uint32_t> SizeOfFunction;
136+
Optional<int32_t> SymIdxOfNextBeyond;
137+
138+
FunctionAuxEnt() : AuxSymbolEnt(AuxSymbolType::AUX_FCN) {}
139+
static bool classof(const AuxSymbolEnt *S) {
140+
return S->Type == AuxSymbolType::AUX_FCN;
141+
}
142+
};
143+
144+
struct ExcpetionAuxEnt : AuxSymbolEnt {
145+
Optional<uint64_t> OffsetToExceptionTbl;
146+
Optional<uint32_t> SizeOfFunction;
147+
Optional<int32_t> SymIdxOfNextBeyond;
148+
149+
ExcpetionAuxEnt() : AuxSymbolEnt(AuxSymbolType::AUX_EXCEPT) {}
150+
static bool classof(const AuxSymbolEnt *S) {
151+
return S->Type == AuxSymbolType::AUX_EXCEPT;
152+
}
153+
}; // Only for XCOFF64.
154+
155+
struct BlockAuxEnt : AuxSymbolEnt {
156+
// Only for XCOFF32.
157+
Optional<uint16_t> LineNumHi;
158+
Optional<uint16_t> LineNumLo;
159+
// Only for XCOFF64.
160+
Optional<uint32_t> LineNum;
161+
162+
BlockAuxEnt() : AuxSymbolEnt(AuxSymbolType::AUX_SYM) {}
163+
static bool classof(const AuxSymbolEnt *S) {
164+
return S->Type == AuxSymbolType::AUX_SYM;
165+
}
166+
};
167+
168+
struct SectAuxEntForDWARF : AuxSymbolEnt {
169+
Optional<uint32_t> LengthOfSectionPortion;
170+
Optional<uint32_t> NumberOfRelocEnt;
171+
172+
SectAuxEntForDWARF() : AuxSymbolEnt(AuxSymbolType::AUX_SECT) {}
173+
static bool classof(const AuxSymbolEnt *S) {
174+
return S->Type == AuxSymbolType::AUX_SECT;
175+
}
176+
};
177+
178+
struct SectAuxEntForStat : AuxSymbolEnt {
179+
Optional<uint32_t> SectionLength;
180+
Optional<uint16_t> NumberOfRelocEnt;
181+
Optional<uint16_t> NumberOfLineNum;
182+
183+
SectAuxEntForStat() : AuxSymbolEnt(AuxSymbolType::AUX_STAT) {}
184+
static bool classof(const AuxSymbolEnt *S) {
185+
return S->Type == AuxSymbolType::AUX_STAT;
186+
}
187+
}; // Only for XCOFF32.
188+
85189
struct Symbol {
86190
StringRef SymbolName;
87191
llvm::yaml::Hex64 Value; // Symbol value; storage class-dependent.
88192
Optional<StringRef> SectionName;
89193
Optional<uint16_t> SectionIndex;
90194
llvm::yaml::Hex16 Type;
91195
XCOFF::StorageClass StorageClass;
92-
uint8_t NumberOfAuxEntries;
196+
Optional<uint8_t> NumberOfAuxEntries;
197+
std::vector<std::unique_ptr<AuxSymbolEnt>> AuxEntries;
93198
};
94199

95200
struct StringTable {
@@ -114,6 +219,7 @@ struct Object {
114219
LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Symbol)
115220
LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Relocation)
116221
LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Section)
222+
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::XCOFFYAML::AuxSymbolEnt>)
117223

118224
namespace llvm {
119225
namespace yaml {
@@ -126,6 +232,18 @@ template <> struct ScalarEnumerationTraits<XCOFF::StorageClass> {
126232
static void enumeration(IO &IO, XCOFF::StorageClass &Value);
127233
};
128234

235+
template <> struct ScalarEnumerationTraits<XCOFF::StorageMappingClass> {
236+
static void enumeration(IO &IO, XCOFF::StorageMappingClass &Value);
237+
};
238+
239+
template <> struct ScalarEnumerationTraits<XCOFF::CFileStringType> {
240+
static void enumeration(IO &IO, XCOFF::CFileStringType &Type);
241+
};
242+
243+
template <> struct ScalarEnumerationTraits<XCOFFYAML::AuxSymbolType> {
244+
static void enumeration(IO &IO, XCOFFYAML::AuxSymbolType &Type);
245+
};
246+
129247
template <> struct MappingTraits<XCOFFYAML::FileHeader> {
130248
static void mapping(IO &IO, XCOFFYAML::FileHeader &H);
131249
};
@@ -134,6 +252,10 @@ template <> struct MappingTraits<XCOFFYAML::AuxiliaryHeader> {
134252
static void mapping(IO &IO, XCOFFYAML::AuxiliaryHeader &AuxHdr);
135253
};
136254

255+
template <> struct MappingTraits<std::unique_ptr<XCOFFYAML::AuxSymbolEnt>> {
256+
static void mapping(IO &IO, std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym);
257+
};
258+
137259
template <> struct MappingTraits<XCOFFYAML::Symbol> {
138260
static void mapping(IO &IO, XCOFFYAML::Symbol &S);
139261
};

llvm/lib/ObjectYAML/XCOFFEmitter.cpp

Lines changed: 174 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class XCOFFWriter {
4747
bool initRelocations(uint64_t &CurrentOffset);
4848
bool initStringTable();
4949
bool assignAddressesAndIndices();
50+
5051
void writeFileHeader();
5152
void writeAuxFileHeader();
5253
void writeSectionHeader();
@@ -55,6 +56,15 @@ class XCOFFWriter {
5556
bool writeSymbols();
5657
void writeStringTable();
5758

59+
void writeAuxSymbol(const XCOFFYAML::CsectAuxEnt &AuxSym);
60+
void writeAuxSymbol(const XCOFFYAML::FileAuxEnt &AuxSym);
61+
void writeAuxSymbol(const XCOFFYAML::FunctionAuxEnt &AuxSym);
62+
void writeAuxSymbol(const XCOFFYAML::ExcpetionAuxEnt &AuxSym);
63+
void writeAuxSymbol(const XCOFFYAML::BlockAuxEnt &AuxSym);
64+
void writeAuxSymbol(const XCOFFYAML::SectAuxEntForDWARF &AuxSym);
65+
void writeAuxSymbol(const XCOFFYAML::SectAuxEntForStat &AuxSym);
66+
void writeAuxSymbol(const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym);
67+
5868
XCOFFYAML::Object &Obj;
5969
bool Is64Bit = false;
6070
support::endian::Writer W;
@@ -190,12 +200,23 @@ bool XCOFFWriter::initStringTable() {
190200
}
191201
}
192202
} else {
193-
for (XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
203+
for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
194204
if (nameShouldBeInStringTable(YamlSym.SymbolName))
195205
StrTblBuilder.add(YamlSym.SymbolName);
196206
}
197207
}
198208

209+
// Check if the file name in the File Auxiliary Entry should be added to the
210+
// string table.
211+
for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
212+
for (const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym :
213+
YamlSym.AuxEntries) {
214+
if (auto AS = dyn_cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()))
215+
if (nameShouldBeInStringTable(AS->FileNameOrString.getValueOr("")))
216+
StrTblBuilder.add(AS->FileNameOrString.getValueOr(""));
217+
}
218+
}
219+
199220
StrTblBuilder.finalize();
200221

201222
size_t StrTblSize = StrTblBuilder.getSize();
@@ -216,9 +237,21 @@ bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) {
216237
InitFileHdr.NumberOfSections = Obj.Sections.size();
217238
InitFileHdr.NumberOfSymTableEntries = Obj.Symbols.size();
218239

219-
for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols)
240+
for (XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
241+
uint32_t AuxCount = YamlSym.AuxEntries.size();
242+
if (YamlSym.NumberOfAuxEntries && *YamlSym.NumberOfAuxEntries < AuxCount) {
243+
ErrHandler("specified NumberOfAuxEntries " +
244+
Twine(static_cast<uint32_t>(*YamlSym.NumberOfAuxEntries)) +
245+
" is less than the actual number "
246+
"of auxiliary entries " +
247+
Twine(AuxCount));
248+
return false;
249+
}
250+
YamlSym.NumberOfAuxEntries =
251+
YamlSym.NumberOfAuxEntries.getValueOr(AuxCount);
220252
// Add the number of auxiliary symbols to the total number.
221-
InitFileHdr.NumberOfSymTableEntries += YamlSym.NumberOfAuxEntries;
253+
InitFileHdr.NumberOfSymTableEntries += *YamlSym.NumberOfAuxEntries;
254+
}
222255

223256
// Calculate SymbolTableOffset for the file header.
224257
if (InitFileHdr.NumberOfSymTableEntries) {
@@ -491,6 +524,125 @@ bool XCOFFWriter::writeRelocations() {
491524
return true;
492525
}
493526

527+
void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::CsectAuxEnt &AuxSym) {
528+
if (Is64Bit) {
529+
W.write<uint32_t>(AuxSym.SectionOrLengthLo.getValueOr(0));
530+
W.write<uint32_t>(AuxSym.ParameterHashIndex.getValueOr(0));
531+
W.write<uint16_t>(AuxSym.TypeChkSectNum.getValueOr(0));
532+
W.write<uint8_t>(AuxSym.SymbolAlignmentAndType.getValueOr(0));
533+
W.write<uint8_t>(AuxSym.StorageMappingClass.getValueOr(XCOFF::XMC_PR));
534+
W.write<uint32_t>(AuxSym.SectionOrLengthHi.getValueOr(0));
535+
W.write<uint8_t>(0);
536+
W.write<uint8_t>(XCOFF::AUX_CSECT);
537+
} else {
538+
W.write<uint32_t>(AuxSym.SectionOrLength.getValueOr(0));
539+
W.write<uint32_t>(AuxSym.ParameterHashIndex.getValueOr(0));
540+
W.write<uint16_t>(AuxSym.TypeChkSectNum.getValueOr(0));
541+
W.write<uint8_t>(AuxSym.SymbolAlignmentAndType.getValueOr(0));
542+
W.write<uint8_t>(AuxSym.StorageMappingClass.getValueOr(XCOFF::XMC_PR));
543+
W.write<uint32_t>(AuxSym.StabInfoIndex.getValueOr(0));
544+
W.write<uint16_t>(AuxSym.StabSectNum.getValueOr(0));
545+
}
546+
}
547+
548+
void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::ExcpetionAuxEnt &AuxSym) {
549+
assert(Is64Bit && "can't write the exception auxiliary symbol for XCOFF32");
550+
W.write<uint64_t>(AuxSym.OffsetToExceptionTbl.getValueOr(0));
551+
W.write<uint32_t>(AuxSym.SizeOfFunction.getValueOr(0));
552+
W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.getValueOr(0));
553+
W.write<uint8_t>(0);
554+
W.write<uint8_t>(XCOFF::AUX_EXCEPT);
555+
}
556+
557+
void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::FunctionAuxEnt &AuxSym) {
558+
if (Is64Bit) {
559+
W.write<uint64_t>(AuxSym.PtrToLineNum.getValueOr(0));
560+
W.write<uint32_t>(AuxSym.SizeOfFunction.getValueOr(0));
561+
W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.getValueOr(0));
562+
W.write<uint8_t>(0);
563+
W.write<uint8_t>(XCOFF::AUX_FCN);
564+
} else {
565+
W.write<uint32_t>(AuxSym.OffsetToExceptionTbl.getValueOr(0));
566+
W.write<uint32_t>(AuxSym.SizeOfFunction.getValueOr(0));
567+
W.write<uint32_t>(AuxSym.PtrToLineNum.getValueOr(0));
568+
W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.getValueOr(0));
569+
W.OS.write_zeros(2);
570+
}
571+
}
572+
573+
void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::FileAuxEnt &AuxSym) {
574+
StringRef FileName = AuxSym.FileNameOrString.getValueOr("");
575+
if (nameShouldBeInStringTable(FileName)) {
576+
W.write<int32_t>(0);
577+
W.write<uint32_t>(StrTblBuilder.getOffset(FileName));
578+
} else {
579+
writeName(FileName, W);
580+
}
581+
W.OS.write_zeros(XCOFF::FileNamePadSize);
582+
W.write<uint8_t>(AuxSym.FileStringType.getValueOr(XCOFF::XFT_FN));
583+
if (Is64Bit) {
584+
W.OS.write_zeros(2);
585+
W.write<uint8_t>(XCOFF::AUX_FILE);
586+
} else {
587+
W.OS.write_zeros(3);
588+
}
589+
}
590+
591+
void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::BlockAuxEnt &AuxSym) {
592+
if (Is64Bit) {
593+
W.write<uint32_t>(AuxSym.LineNum.getValueOr(0));
594+
W.OS.write_zeros(13);
595+
W.write<uint8_t>(XCOFF::AUX_SYM);
596+
} else {
597+
W.OS.write_zeros(2);
598+
W.write<uint16_t>(AuxSym.LineNumHi.getValueOr(0));
599+
W.write<uint16_t>(AuxSym.LineNumLo.getValueOr(0));
600+
W.OS.write_zeros(12);
601+
}
602+
}
603+
604+
void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::SectAuxEntForDWARF &AuxSym) {
605+
if (Is64Bit) {
606+
W.write<uint64_t>(AuxSym.LengthOfSectionPortion.getValueOr(0));
607+
W.write<uint64_t>(AuxSym.NumberOfRelocEnt.getValueOr(0));
608+
W.write<uint8_t>(0);
609+
W.write<uint8_t>(XCOFF::AUX_SECT);
610+
} else {
611+
W.write<uint32_t>(AuxSym.LengthOfSectionPortion.getValueOr(0));
612+
W.OS.write_zeros(4);
613+
W.write<uint32_t>(AuxSym.NumberOfRelocEnt.getValueOr(0));
614+
W.OS.write_zeros(6);
615+
}
616+
}
617+
618+
void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::SectAuxEntForStat &AuxSym) {
619+
assert(!Is64Bit && "can't write the stat auxiliary symbol for XCOFF64");
620+
W.write<uint32_t>(AuxSym.SectionLength.getValueOr(0));
621+
W.write<uint16_t>(AuxSym.NumberOfRelocEnt.getValueOr(0));
622+
W.write<uint16_t>(AuxSym.NumberOfLineNum.getValueOr(0));
623+
W.OS.write_zeros(10);
624+
}
625+
626+
void XCOFFWriter::writeAuxSymbol(
627+
const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym) {
628+
if (auto AS = dyn_cast<XCOFFYAML::CsectAuxEnt>(AuxSym.get()))
629+
writeAuxSymbol(*AS);
630+
else if (auto AS = dyn_cast<XCOFFYAML::FunctionAuxEnt>(AuxSym.get()))
631+
writeAuxSymbol(*AS);
632+
else if (auto AS = dyn_cast<XCOFFYAML::ExcpetionAuxEnt>(AuxSym.get()))
633+
writeAuxSymbol(*AS);
634+
else if (auto AS = dyn_cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()))
635+
writeAuxSymbol(*AS);
636+
else if (auto AS = dyn_cast<XCOFFYAML::BlockAuxEnt>(AuxSym.get()))
637+
writeAuxSymbol(*AS);
638+
else if (auto AS = dyn_cast<XCOFFYAML::SectAuxEntForDWARF>(AuxSym.get()))
639+
writeAuxSymbol(*AS);
640+
else if (auto AS = dyn_cast<XCOFFYAML::SectAuxEntForStat>(AuxSym.get()))
641+
writeAuxSymbol(*AS);
642+
else
643+
llvm_unreachable("unknown auxiliary symbol type");
644+
}
645+
494646
bool XCOFFWriter::writeSymbols() {
495647
int64_t PaddingSize =
496648
(uint64_t)InitFileHdr.SymbolTableOffset - (W.OS.tell() - StartOffset);
@@ -533,16 +685,25 @@ bool XCOFFWriter::writeSymbols() {
533685
}
534686
W.write<uint16_t>(YamlSym.Type);
535687
W.write<uint8_t>(YamlSym.StorageClass);
536-
W.write<uint8_t>(YamlSym.NumberOfAuxEntries);
537-
538-
// Now output the auxiliary entry.
539-
for (uint8_t I = 0, E = YamlSym.NumberOfAuxEntries; I < E; ++I) {
540-
// TODO: Auxiliary entry is not supported yet.
541-
// The auxiliary entries for a symbol follow its symbol table entry. The
542-
// length of each auxiliary entry is the same as a symbol table entry (18
543-
// bytes). The format and quantity of auxiliary entries depend on the
544-
// storage class (n_sclass) and type (n_type) of the symbol table entry.
545-
W.OS.write_zeros(XCOFF::SymbolTableEntrySize);
688+
689+
uint8_t NumOfAuxSym = YamlSym.NumberOfAuxEntries.getValueOr(0);
690+
W.write<uint8_t>(NumOfAuxSym);
691+
692+
if (!NumOfAuxSym && !YamlSym.AuxEntries.size())
693+
continue;
694+
695+
// Now write auxiliary entries.
696+
if (!YamlSym.AuxEntries.size()) {
697+
W.OS.write_zeros(XCOFF::SymbolTableEntrySize * NumOfAuxSym);
698+
} else {
699+
for (const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym :
700+
YamlSym.AuxEntries) {
701+
writeAuxSymbol(AuxSym);
702+
}
703+
// Pad with zeros.
704+
if (NumOfAuxSym > YamlSym.AuxEntries.size())
705+
W.OS.write_zeros(XCOFF::SymbolTableEntrySize *
706+
(NumOfAuxSym - YamlSym.AuxEntries.size()));
546707
}
547708
}
548709
return true;

0 commit comments

Comments
 (0)