1//===-- XCOFFYAML.cpp - XCOFF YAMLIO 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 defines classes for handling the YAML representation of XCOFF.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/ObjectYAML/XCOFFYAML.h"
14#include "llvm/BinaryFormat/XCOFF.h"
15#include <string.h>
16
17namespace llvm {
18namespace XCOFFYAML {
19
20Object::Object() { memset(&Header, 0, sizeof(Header)); }
21
22AuxSymbolEnt::~AuxSymbolEnt() = default;
23
24} // namespace XCOFFYAML
25
26namespace yaml {
27
28void ScalarBitSetTraits<XCOFF::SectionTypeFlags>::bitset(
29    IO &IO, XCOFF::SectionTypeFlags &Value) {
30#define ECase(X) IO.bitSetCase(Value, #X, XCOFF::X)
31  ECase(STYP_PAD);
32  ECase(STYP_DWARF);
33  ECase(STYP_TEXT);
34  ECase(STYP_DATA);
35  ECase(STYP_BSS);
36  ECase(STYP_EXCEPT);
37  ECase(STYP_INFO);
38  ECase(STYP_TDATA);
39  ECase(STYP_TBSS);
40  ECase(STYP_LOADER);
41  ECase(STYP_DEBUG);
42  ECase(STYP_TYPCHK);
43  ECase(STYP_OVRFLO);
44#undef ECase
45}
46
47void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
48    IO &IO, XCOFF::StorageClass &Value) {
49#define ECase(X) IO.enumCase(Value, #X, XCOFF::X)
50  ECase(C_NULL);
51  ECase(C_AUTO);
52  ECase(C_EXT);
53  ECase(C_STAT);
54  ECase(C_REG);
55  ECase(C_EXTDEF);
56  ECase(C_LABEL);
57  ECase(C_ULABEL);
58  ECase(C_MOS);
59  ECase(C_ARG);
60  ECase(C_STRTAG);
61  ECase(C_MOU);
62  ECase(C_UNTAG);
63  ECase(C_TPDEF);
64  ECase(C_USTATIC);
65  ECase(C_ENTAG);
66  ECase(C_MOE);
67  ECase(C_REGPARM);
68  ECase(C_FIELD);
69  ECase(C_BLOCK);
70  ECase(C_FCN);
71  ECase(C_EOS);
72  ECase(C_FILE);
73  ECase(C_LINE);
74  ECase(C_ALIAS);
75  ECase(C_HIDDEN);
76  ECase(C_HIDEXT);
77  ECase(C_BINCL);
78  ECase(C_EINCL);
79  ECase(C_INFO);
80  ECase(C_WEAKEXT);
81  ECase(C_DWARF);
82  ECase(C_GSYM);
83  ECase(C_LSYM);
84  ECase(C_PSYM);
85  ECase(C_RSYM);
86  ECase(C_RPSYM);
87  ECase(C_STSYM);
88  ECase(C_TCSYM);
89  ECase(C_BCOMM);
90  ECase(C_ECOML);
91  ECase(C_ECOMM);
92  ECase(C_DECL);
93  ECase(C_ENTRY);
94  ECase(C_FUN);
95  ECase(C_BSTAT);
96  ECase(C_ESTAT);
97  ECase(C_GTLS);
98  ECase(C_STTLS);
99  ECase(C_EFCN);
100#undef ECase
101}
102
103void ScalarEnumerationTraits<XCOFF::StorageMappingClass>::enumeration(
104    IO &IO, XCOFF::StorageMappingClass &Value) {
105#define ECase(X) IO.enumCase(Value, #X, XCOFF::X)
106  ECase(XMC_PR);
107  ECase(XMC_RO);
108  ECase(XMC_DB);
109  ECase(XMC_GL);
110  ECase(XMC_XO);
111  ECase(XMC_SV);
112  ECase(XMC_SV64);
113  ECase(XMC_SV3264);
114  ECase(XMC_TI);
115  ECase(XMC_TB);
116  ECase(XMC_RW);
117  ECase(XMC_TC0);
118  ECase(XMC_TC);
119  ECase(XMC_TD);
120  ECase(XMC_DS);
121  ECase(XMC_UA);
122  ECase(XMC_BS);
123  ECase(XMC_UC);
124  ECase(XMC_TL);
125  ECase(XMC_UL);
126  ECase(XMC_TE);
127#undef ECase
128}
129
130void ScalarEnumerationTraits<XCOFFYAML::AuxSymbolType>::enumeration(
131    IO &IO, XCOFFYAML::AuxSymbolType &Type) {
132#define ECase(X) IO.enumCase(Type, #X, XCOFFYAML::X)
133  ECase(AUX_EXCEPT);
134  ECase(AUX_FCN);
135  ECase(AUX_SYM);
136  ECase(AUX_FILE);
137  ECase(AUX_CSECT);
138  ECase(AUX_SECT);
139  ECase(AUX_STAT);
140#undef ECase
141}
142
143void ScalarEnumerationTraits<XCOFF::CFileStringType>::enumeration(
144    IO &IO, XCOFF::CFileStringType &Type) {
145#define ECase(X) IO.enumCase(Type, #X, XCOFF::X)
146  ECase(XFT_FN);
147  ECase(XFT_CT);
148  ECase(XFT_CV);
149  ECase(XFT_CD);
150#undef ECase
151}
152
153struct NSectionFlags {
154  NSectionFlags(IO &) : Flags(XCOFF::SectionTypeFlags(0)) {}
155  NSectionFlags(IO &, uint32_t C) : Flags(XCOFF::SectionTypeFlags(C)) {}
156
157  uint32_t denormalize(IO &) { return Flags; }
158
159  XCOFF::SectionTypeFlags Flags;
160};
161
162void MappingTraits<XCOFFYAML::FileHeader>::mapping(
163    IO &IO, XCOFFYAML::FileHeader &FileHdr) {
164  IO.mapOptional("MagicNumber", FileHdr.Magic);
165  IO.mapOptional("NumberOfSections", FileHdr.NumberOfSections);
166  IO.mapOptional("CreationTime", FileHdr.TimeStamp);
167  IO.mapOptional("OffsetToSymbolTable", FileHdr.SymbolTableOffset);
168  IO.mapOptional("EntriesInSymbolTable", FileHdr.NumberOfSymTableEntries);
169  IO.mapOptional("AuxiliaryHeaderSize", FileHdr.AuxHeaderSize);
170  IO.mapOptional("Flags", FileHdr.Flags);
171}
172
173void MappingTraits<XCOFFYAML::AuxiliaryHeader>::mapping(
174    IO &IO, XCOFFYAML::AuxiliaryHeader &AuxHdr) {
175  IO.mapOptional("Magic", AuxHdr.Magic);
176  IO.mapOptional("Version", AuxHdr.Version);
177  IO.mapOptional("TextStartAddr", AuxHdr.TextStartAddr);
178  IO.mapOptional("DataStartAddr", AuxHdr.DataStartAddr);
179  IO.mapOptional("TOCAnchorAddr", AuxHdr.TOCAnchorAddr);
180  IO.mapOptional("TextSectionSize", AuxHdr.TextSize);
181  IO.mapOptional("DataSectionSize", AuxHdr.InitDataSize);
182  IO.mapOptional("BssSectionSize", AuxHdr.BssDataSize);
183  IO.mapOptional("SecNumOfEntryPoint", AuxHdr.SecNumOfEntryPoint);
184  IO.mapOptional("SecNumOfText", AuxHdr.SecNumOfText);
185  IO.mapOptional("SecNumOfData", AuxHdr.SecNumOfData);
186  IO.mapOptional("SecNumOfTOC", AuxHdr.SecNumOfTOC);
187  IO.mapOptional("SecNumOfLoader", AuxHdr.SecNumOfLoader);
188  IO.mapOptional("SecNumOfBSS", AuxHdr.SecNumOfBSS);
189  IO.mapOptional("MaxAlignOfText", AuxHdr.MaxAlignOfText);
190  IO.mapOptional("MaxAlignOfData", AuxHdr.MaxAlignOfData);
191  IO.mapOptional("ModuleType", AuxHdr.CpuFlag);
192  IO.mapOptional("TextPageSize", AuxHdr.TextPageSize);
193  IO.mapOptional("DataPageSize", AuxHdr.DataPageSize);
194  IO.mapOptional("StackPageSize", AuxHdr.StackPageSize);
195  IO.mapOptional("FlagAndTDataAlignment", AuxHdr.FlagAndTDataAlignment);
196  IO.mapOptional("EntryPointAddr", AuxHdr.EntryPointAddr);
197  IO.mapOptional("MaxStackSize", AuxHdr.MaxStackSize);
198  IO.mapOptional("MaxDataSize", AuxHdr.MaxDataSize);
199  IO.mapOptional("SecNumOfTData", AuxHdr.SecNumOfTData);
200  IO.mapOptional("SecNumOfTBSS", AuxHdr.SecNumOfTBSS);
201  IO.mapOptional("Flag", AuxHdr.Flag);
202}
203
204void MappingTraits<XCOFFYAML::Relocation>::mapping(IO &IO,
205                                                   XCOFFYAML::Relocation &R) {
206  IO.mapOptional("Address", R.VirtualAddress);
207  IO.mapOptional("Symbol", R.SymbolIndex);
208  IO.mapOptional("Info", R.Info);
209  IO.mapOptional("Type", R.Type);
210}
211
212void MappingTraits<XCOFFYAML::Section>::mapping(IO &IO,
213                                                XCOFFYAML::Section &Sec) {
214  MappingNormalization<NSectionFlags, uint32_t> NC(IO, Sec.Flags);
215  IO.mapOptional("Name", Sec.SectionName);
216  IO.mapOptional("Address", Sec.Address);
217  IO.mapOptional("Size", Sec.Size);
218  IO.mapOptional("FileOffsetToData", Sec.FileOffsetToData);
219  IO.mapOptional("FileOffsetToRelocations", Sec.FileOffsetToRelocations);
220  IO.mapOptional("FileOffsetToLineNumbers", Sec.FileOffsetToLineNumbers);
221  IO.mapOptional("NumberOfRelocations", Sec.NumberOfRelocations);
222  IO.mapOptional("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
223  IO.mapOptional("Flags", NC->Flags);
224  IO.mapOptional("SectionData", Sec.SectionData);
225  IO.mapOptional("Relocations", Sec.Relocations);
226}
227
228static void auxSymMapping(IO &IO, XCOFFYAML::CsectAuxEnt &AuxSym, bool Is64) {
229  IO.mapOptional("ParameterHashIndex", AuxSym.ParameterHashIndex);
230  IO.mapOptional("TypeChkSectNum", AuxSym.TypeChkSectNum);
231  IO.mapOptional("SymbolAlignmentAndType", AuxSym.SymbolAlignmentAndType);
232  IO.mapOptional("StorageMappingClass", AuxSym.StorageMappingClass);
233  if (Is64) {
234    IO.mapOptional("SectionOrLengthLo", AuxSym.SectionOrLengthLo);
235    IO.mapOptional("SectionOrLengthHi", AuxSym.SectionOrLengthHi);
236  } else {
237    IO.mapOptional("SectionOrLength", AuxSym.SectionOrLength);
238    IO.mapOptional("StabInfoIndex", AuxSym.StabInfoIndex);
239    IO.mapOptional("StabSectNum", AuxSym.StabSectNum);
240  }
241}
242
243static void auxSymMapping(IO &IO, XCOFFYAML::FileAuxEnt &AuxSym) {
244  IO.mapOptional("FileNameOrString", AuxSym.FileNameOrString);
245  IO.mapOptional("FileStringType", AuxSym.FileStringType);
246}
247
248static void auxSymMapping(IO &IO, XCOFFYAML::BlockAuxEnt &AuxSym, bool Is64) {
249  if (Is64) {
250    IO.mapOptional("LineNum", AuxSym.LineNum);
251  } else {
252    IO.mapOptional("LineNumHi", AuxSym.LineNumHi);
253    IO.mapOptional("LineNumLo", AuxSym.LineNumLo);
254  }
255}
256
257static void auxSymMapping(IO &IO, XCOFFYAML::FunctionAuxEnt &AuxSym,
258                          bool Is64) {
259  if (!Is64)
260    IO.mapOptional("OffsetToExceptionTbl", AuxSym.OffsetToExceptionTbl);
261  IO.mapOptional("SizeOfFunction", AuxSym.SizeOfFunction);
262  IO.mapOptional("SymIdxOfNextBeyond", AuxSym.SymIdxOfNextBeyond);
263  IO.mapOptional("PtrToLineNum", AuxSym.PtrToLineNum);
264}
265
266static void auxSymMapping(IO &IO, XCOFFYAML::ExcpetionAuxEnt &AuxSym) {
267  IO.mapOptional("OffsetToExceptionTbl", AuxSym.OffsetToExceptionTbl);
268  IO.mapOptional("SizeOfFunction", AuxSym.SizeOfFunction);
269  IO.mapOptional("SymIdxOfNextBeyond", AuxSym.SymIdxOfNextBeyond);
270}
271
272static void auxSymMapping(IO &IO, XCOFFYAML::SectAuxEntForDWARF &AuxSym) {
273  IO.mapOptional("LengthOfSectionPortion", AuxSym.LengthOfSectionPortion);
274  IO.mapOptional("NumberOfRelocEnt", AuxSym.NumberOfRelocEnt);
275}
276
277static void auxSymMapping(IO &IO, XCOFFYAML::SectAuxEntForStat &AuxSym) {
278  IO.mapOptional("SectionLength", AuxSym.SectionLength);
279  IO.mapOptional("NumberOfRelocEnt", AuxSym.NumberOfRelocEnt);
280  IO.mapOptional("NumberOfLineNum", AuxSym.NumberOfLineNum);
281}
282
283template <typename AuxEntT>
284static void ResetAuxSym(IO &IO,
285                        std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym) {
286  if (!IO.outputting())
287    AuxSym.reset(new AuxEntT);
288}
289
290void MappingTraits<std::unique_ptr<XCOFFYAML::AuxSymbolEnt>>::mapping(
291    IO &IO, std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym) {
292  const bool Is64 =
293      static_cast<XCOFFYAML::Object *>(IO.getContext())->Header.Magic ==
294      (llvm::yaml::Hex16)XCOFF::XCOFF64;
295
296  XCOFFYAML::AuxSymbolType AuxType;
297  if (IO.outputting())
298    AuxType = AuxSym.get()->Type;
299  IO.mapRequired("Type", AuxType);
300  switch (AuxType) {
301  case XCOFFYAML::AUX_EXCEPT:
302    if (!Is64) {
303      IO.setError("an auxiliary symbol of type AUX_EXCEPT cannot be defined in "
304                  "XCOFF32");
305      return;
306    }
307    ResetAuxSym<XCOFFYAML::ExcpetionAuxEnt>(IO, AuxSym);
308    auxSymMapping(IO, *cast<XCOFFYAML::ExcpetionAuxEnt>(AuxSym.get()));
309    break;
310  case XCOFFYAML::AUX_FCN:
311    ResetAuxSym<XCOFFYAML::FunctionAuxEnt>(IO, AuxSym);
312    auxSymMapping(IO, *cast<XCOFFYAML::FunctionAuxEnt>(AuxSym.get()), Is64);
313    break;
314  case XCOFFYAML::AUX_SYM:
315    ResetAuxSym<XCOFFYAML::BlockAuxEnt>(IO, AuxSym);
316    auxSymMapping(IO, *cast<XCOFFYAML::BlockAuxEnt>(AuxSym.get()), Is64);
317    break;
318  case XCOFFYAML::AUX_FILE:
319    ResetAuxSym<XCOFFYAML::FileAuxEnt>(IO, AuxSym);
320    auxSymMapping(IO, *cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()));
321    break;
322  case XCOFFYAML::AUX_CSECT:
323    ResetAuxSym<XCOFFYAML::CsectAuxEnt>(IO, AuxSym);
324    auxSymMapping(IO, *cast<XCOFFYAML::CsectAuxEnt>(AuxSym.get()), Is64);
325    break;
326  case XCOFFYAML::AUX_SECT:
327    ResetAuxSym<XCOFFYAML::SectAuxEntForDWARF>(IO, AuxSym);
328    auxSymMapping(IO, *cast<XCOFFYAML::SectAuxEntForDWARF>(AuxSym.get()));
329    break;
330  case XCOFFYAML::AUX_STAT:
331    if (Is64) {
332      IO.setError(
333          "an auxiliary symbol of type AUX_STAT cannot be defined in XCOFF64");
334      return;
335    }
336    ResetAuxSym<XCOFFYAML::SectAuxEntForStat>(IO, AuxSym);
337    auxSymMapping(IO, *cast<XCOFFYAML::SectAuxEntForStat>(AuxSym.get()));
338    break;
339  }
340}
341
342void MappingTraits<XCOFFYAML::Symbol>::mapping(IO &IO, XCOFFYAML::Symbol &S) {
343  IO.mapOptional("Name", S.SymbolName);
344  IO.mapOptional("Value", S.Value);
345  IO.mapOptional("Section", S.SectionName);
346  IO.mapOptional("SectionIndex", S.SectionIndex);
347  IO.mapOptional("Type", S.Type);
348  IO.mapOptional("StorageClass", S.StorageClass);
349  IO.mapOptional("NumberOfAuxEntries", S.NumberOfAuxEntries);
350  IO.mapOptional("AuxEntries", S.AuxEntries);
351}
352
353void MappingTraits<XCOFFYAML::StringTable>::mapping(IO &IO, XCOFFYAML::StringTable &Str) {
354  IO.mapOptional("ContentSize", Str.ContentSize);
355  IO.mapOptional("Length", Str.Length);
356  IO.mapOptional("Strings", Str.Strings);
357  IO.mapOptional("RawContent", Str.RawContent);
358}
359
360void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) {
361  IO.setContext(&Obj);
362  IO.mapTag("!XCOFF", true);
363  IO.mapRequired("FileHeader", Obj.Header);
364  IO.mapOptional("AuxiliaryHeader", Obj.AuxHeader);
365  IO.mapOptional("Sections", Obj.Sections);
366  IO.mapOptional("Symbols", Obj.Symbols);
367  IO.mapOptional("StringTable", Obj.StrTbl);
368  IO.setContext(nullptr);
369}
370
371} // namespace yaml
372} // namespace llvm
373