1 //===-- llvm/BinaryFormat/XCOFF.cpp - The XCOFF file format -----*- 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 #include "llvm/BinaryFormat/XCOFF.h"
10 #include "llvm/ADT/SmallString.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/Errc.h"
13 #include "llvm/Support/Error.h"
14 
15 using namespace llvm;
16 
17 #define SMC_CASE(A)                                                            \
18   case XCOFF::XMC_##A:                                                         \
19     return #A;
20 StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) {
21   switch (SMC) {
22     SMC_CASE(PR)
23     SMC_CASE(RO)
24     SMC_CASE(DB)
25     SMC_CASE(GL)
26     SMC_CASE(XO)
27     SMC_CASE(SV)
28     SMC_CASE(SV64)
29     SMC_CASE(SV3264)
30     SMC_CASE(TI)
31     SMC_CASE(TB)
32     SMC_CASE(RW)
33     SMC_CASE(TC0)
34     SMC_CASE(TC)
35     SMC_CASE(TD)
36     SMC_CASE(DS)
37     SMC_CASE(UA)
38     SMC_CASE(BS)
39     SMC_CASE(UC)
40     SMC_CASE(TL)
41     SMC_CASE(UL)
42     SMC_CASE(TE)
43 #undef SMC_CASE
44   }
45 
46   // TODO: need to add a test case for "Unknown" and other SMC.
47   return "Unknown";
48 }
49 
50 #define RELOC_CASE(A)                                                          \
51   case XCOFF::A:                                                               \
52     return #A;
53 StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) {
54   switch (Type) {
55     RELOC_CASE(R_POS)
56     RELOC_CASE(R_RL)
57     RELOC_CASE(R_RLA)
58     RELOC_CASE(R_NEG)
59     RELOC_CASE(R_REL)
60     RELOC_CASE(R_TOC)
61     RELOC_CASE(R_TRL)
62     RELOC_CASE(R_TRLA)
63     RELOC_CASE(R_GL)
64     RELOC_CASE(R_TCL)
65     RELOC_CASE(R_REF)
66     RELOC_CASE(R_BA)
67     RELOC_CASE(R_BR)
68     RELOC_CASE(R_RBA)
69     RELOC_CASE(R_RBR)
70     RELOC_CASE(R_TLS)
71     RELOC_CASE(R_TLS_IE)
72     RELOC_CASE(R_TLS_LD)
73     RELOC_CASE(R_TLS_LE)
74     RELOC_CASE(R_TLSM)
75     RELOC_CASE(R_TLSML)
76     RELOC_CASE(R_TOCU)
77     RELOC_CASE(R_TOCL)
78   }
79   return "Unknown";
80 }
81 #undef RELOC_CASE
82 
83 #define LANG_CASE(A)                                                           \
84   case XCOFF::TracebackTable::A:                                               \
85     return #A;
86 
87 StringRef XCOFF::getNameForTracebackTableLanguageId(
88     XCOFF::TracebackTable::LanguageID LangId) {
89   switch (LangId) {
90     LANG_CASE(C)
91     LANG_CASE(Fortran)
92     LANG_CASE(Pascal)
93     LANG_CASE(Ada)
94     LANG_CASE(PL1)
95     LANG_CASE(Basic)
96     LANG_CASE(Lisp)
97     LANG_CASE(Cobol)
98     LANG_CASE(Modula2)
99     LANG_CASE(Rpg)
100     LANG_CASE(PL8)
101     LANG_CASE(Assembly)
102     LANG_CASE(Java)
103     LANG_CASE(ObjectiveC)
104     LANG_CASE(CPlusPlus)
105   }
106   return "Unknown";
107 }
108 #undef LANG_CASE
109 
110 Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value,
111                                                 unsigned FixedParmsNum,
112                                                 unsigned FloatingParmsNum) {
113   SmallString<32> ParmsType;
114   int Bits = 0;
115   unsigned ParsedFixedNum = 0;
116   unsigned ParsedFloatingNum = 0;
117   unsigned ParsedNum = 0;
118   unsigned ParmsNum = FixedParmsNum + FloatingParmsNum;
119 
120   while (Bits < 32 && ParsedNum < ParmsNum) {
121     if (++ParsedNum > 1)
122       ParmsType += ", ";
123     if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) {
124       // Fixed parameter type.
125       ParmsType += "i";
126       ++ParsedFixedNum;
127       Value <<= 1;
128       ++Bits;
129     } else {
130       if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0)
131         // Float parameter type.
132         ParmsType += "f";
133       else
134         // Double parameter type.
135         ParmsType += "d";
136       ++ParsedFloatingNum;
137       Value <<= 2;
138       Bits += 2;
139     }
140   }
141 
142   // We have more parameters than the 32 Bits could encode.
143   if (ParsedNum < ParmsNum)
144     ParmsType += ", ...";
145 
146   if (Value != 0u || ParsedFixedNum > FixedParmsNum ||
147       ParsedFloatingNum > FloatingParmsNum)
148     return createStringError(errc::invalid_argument,
149                              "ParmsType encodes can not map to ParmsNum "
150                              "parameters in parseParmsType.");
151   return ParmsType;
152 }
153 
154 SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) {
155   SmallString<32> Res;
156 
157   if (Flag & ExtendedTBTableFlag::TB_OS1)
158     Res += "TB_OS1 ";
159   if (Flag & ExtendedTBTableFlag::TB_RESERVED)
160     Res += "TB_RESERVED ";
161   if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY)
162     Res += "TB_SSP_CANARY ";
163   if (Flag & ExtendedTBTableFlag::TB_OS2)
164     Res += "TB_OS2 ";
165   if (Flag & ExtendedTBTableFlag::TB_EH_INFO)
166     Res += "TB_EH_INFO ";
167   if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2)
168     Res += "TB_LONGTBTABLE2 ";
169 
170   // Two of the bits that haven't got used in the mask.
171   if (Flag & 0x06)
172     Res += "Unknown ";
173 
174   // Pop the last space.
175   Res.pop_back();
176   return Res;
177 }
178 
179 Expected<SmallString<32>>
180 XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum,
181                                  unsigned FloatingParmsNum,
182                                  unsigned VectorParmsNum) {
183   SmallString<32> ParmsType;
184 
185   unsigned ParsedFixedNum = 0;
186   unsigned ParsedFloatingNum = 0;
187   unsigned ParsedVectorNum = 0;
188   unsigned ParsedNum = 0;
189   unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum;
190 
191   for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) {
192     if (++ParsedNum > 1)
193       ParmsType += ", ";
194 
195     switch (Value & TracebackTable::ParmTypeMask) {
196     case TracebackTable::ParmTypeIsFixedBits:
197       ParmsType += "i";
198       ++ParsedFixedNum;
199       break;
200     case TracebackTable::ParmTypeIsVectorBits:
201       ParmsType += "v";
202       ++ParsedVectorNum;
203       break;
204     case TracebackTable::ParmTypeIsFloatingBits:
205       ParmsType += "f";
206       ++ParsedFloatingNum;
207       break;
208     case TracebackTable::ParmTypeIsDoubleBits:
209       ParmsType += "d";
210       ++ParsedFloatingNum;
211       break;
212     default:
213       assert(false && "Unrecognized bits in ParmsType.");
214     }
215     Value <<= 2;
216   }
217 
218   // We have more parameters than the 32 Bits could encode.
219   if (ParsedNum < ParmsNum)
220     ParmsType += ", ...";
221 
222   if (Value != 0u || ParsedFixedNum > FixedParmsNum ||
223       ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum)
224     return createStringError(
225         errc::invalid_argument,
226         "ParmsType encodes can not map to ParmsNum parameters "
227         "in parseParmsTypeWithVecInfo.");
228 
229   return ParmsType;
230 }
231 
232 Expected<SmallString<32>> XCOFF::parseVectorParmsType(uint32_t Value,
233                                                       unsigned ParmsNum) {
234   SmallString<32> ParmsType;
235   unsigned ParsedNum = 0;
236   for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) {
237     if (++ParsedNum > 1)
238       ParmsType += ", ";
239     switch (Value & TracebackTable::ParmTypeMask) {
240     case TracebackTable::ParmTypeIsVectorCharBit:
241       ParmsType += "vc";
242       break;
243 
244     case TracebackTable::ParmTypeIsVectorShortBit:
245       ParmsType += "vs";
246       break;
247 
248     case TracebackTable::ParmTypeIsVectorIntBit:
249       ParmsType += "vi";
250       break;
251 
252     case TracebackTable::ParmTypeIsVectorFloatBit:
253       ParmsType += "vf";
254       break;
255     }
256 
257     Value <<= 2;
258   }
259 
260   // We have more parameters than the 32 Bits could encode.
261   if (ParsedNum < ParmsNum)
262     ParmsType += ", ...";
263 
264   if (Value != 0u)
265     return createStringError(errc::invalid_argument,
266                              "ParmsType encodes more than ParmsNum parameters "
267                              "in parseVectorParmsType.");
268   return ParmsType;
269 }
270