xref: /freebsd-src/contrib/llvm-project/llvm/lib/BinaryFormat/XCOFF.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1480093f4SDimitry Andric //===-- llvm/BinaryFormat/XCOFF.cpp - The XCOFF file format -----*- C++/-*-===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric 
9480093f4SDimitry Andric #include "llvm/BinaryFormat/XCOFF.h"
10e8d8bef9SDimitry Andric #include "llvm/ADT/SmallString.h"
115ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h"
12*fe6060f1SDimitry Andric #include "llvm/Support/Errc.h"
13*fe6060f1SDimitry Andric #include "llvm/Support/Error.h"
14480093f4SDimitry Andric 
15480093f4SDimitry Andric using namespace llvm;
16480093f4SDimitry Andric 
175ffd83dbSDimitry Andric #define SMC_CASE(A)                                                            \
185ffd83dbSDimitry Andric   case XCOFF::XMC_##A:                                                         \
195ffd83dbSDimitry Andric     return #A;
getMappingClassString(XCOFF::StorageMappingClass SMC)20480093f4SDimitry Andric StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) {
21480093f4SDimitry Andric   switch (SMC) {
225ffd83dbSDimitry Andric     SMC_CASE(PR)
235ffd83dbSDimitry Andric     SMC_CASE(RO)
245ffd83dbSDimitry Andric     SMC_CASE(DB)
255ffd83dbSDimitry Andric     SMC_CASE(GL)
265ffd83dbSDimitry Andric     SMC_CASE(XO)
275ffd83dbSDimitry Andric     SMC_CASE(SV)
285ffd83dbSDimitry Andric     SMC_CASE(SV64)
295ffd83dbSDimitry Andric     SMC_CASE(SV3264)
305ffd83dbSDimitry Andric     SMC_CASE(TI)
315ffd83dbSDimitry Andric     SMC_CASE(TB)
325ffd83dbSDimitry Andric     SMC_CASE(RW)
335ffd83dbSDimitry Andric     SMC_CASE(TC0)
345ffd83dbSDimitry Andric     SMC_CASE(TC)
355ffd83dbSDimitry Andric     SMC_CASE(TD)
365ffd83dbSDimitry Andric     SMC_CASE(DS)
375ffd83dbSDimitry Andric     SMC_CASE(UA)
385ffd83dbSDimitry Andric     SMC_CASE(BS)
395ffd83dbSDimitry Andric     SMC_CASE(UC)
405ffd83dbSDimitry Andric     SMC_CASE(TL)
415ffd83dbSDimitry Andric     SMC_CASE(UL)
425ffd83dbSDimitry Andric     SMC_CASE(TE)
435ffd83dbSDimitry Andric #undef SMC_CASE
44480093f4SDimitry Andric   }
455ffd83dbSDimitry Andric 
465ffd83dbSDimitry Andric   // TODO: need to add a test case for "Unknown" and other SMC.
475ffd83dbSDimitry Andric   return "Unknown";
48480093f4SDimitry Andric }
495ffd83dbSDimitry Andric 
505ffd83dbSDimitry Andric #define RELOC_CASE(A)                                                          \
515ffd83dbSDimitry Andric   case XCOFF::A:                                                               \
525ffd83dbSDimitry Andric     return #A;
getRelocationTypeString(XCOFF::RelocationType Type)535ffd83dbSDimitry Andric StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) {
545ffd83dbSDimitry Andric   switch (Type) {
555ffd83dbSDimitry Andric     RELOC_CASE(R_POS)
565ffd83dbSDimitry Andric     RELOC_CASE(R_RL)
575ffd83dbSDimitry Andric     RELOC_CASE(R_RLA)
585ffd83dbSDimitry Andric     RELOC_CASE(R_NEG)
595ffd83dbSDimitry Andric     RELOC_CASE(R_REL)
605ffd83dbSDimitry Andric     RELOC_CASE(R_TOC)
615ffd83dbSDimitry Andric     RELOC_CASE(R_TRL)
625ffd83dbSDimitry Andric     RELOC_CASE(R_TRLA)
635ffd83dbSDimitry Andric     RELOC_CASE(R_GL)
645ffd83dbSDimitry Andric     RELOC_CASE(R_TCL)
655ffd83dbSDimitry Andric     RELOC_CASE(R_REF)
665ffd83dbSDimitry Andric     RELOC_CASE(R_BA)
675ffd83dbSDimitry Andric     RELOC_CASE(R_BR)
685ffd83dbSDimitry Andric     RELOC_CASE(R_RBA)
695ffd83dbSDimitry Andric     RELOC_CASE(R_RBR)
705ffd83dbSDimitry Andric     RELOC_CASE(R_TLS)
715ffd83dbSDimitry Andric     RELOC_CASE(R_TLS_IE)
725ffd83dbSDimitry Andric     RELOC_CASE(R_TLS_LD)
735ffd83dbSDimitry Andric     RELOC_CASE(R_TLS_LE)
745ffd83dbSDimitry Andric     RELOC_CASE(R_TLSM)
755ffd83dbSDimitry Andric     RELOC_CASE(R_TLSML)
765ffd83dbSDimitry Andric     RELOC_CASE(R_TOCU)
775ffd83dbSDimitry Andric     RELOC_CASE(R_TOCL)
785ffd83dbSDimitry Andric   }
795ffd83dbSDimitry Andric   return "Unknown";
805ffd83dbSDimitry Andric }
81*fe6060f1SDimitry Andric #undef RELOC_CASE
82e8d8bef9SDimitry Andric 
83e8d8bef9SDimitry Andric #define LANG_CASE(A)                                                           \
84e8d8bef9SDimitry Andric   case XCOFF::TracebackTable::A:                                               \
85e8d8bef9SDimitry Andric     return #A;
86e8d8bef9SDimitry Andric 
getNameForTracebackTableLanguageId(XCOFF::TracebackTable::LanguageID LangId)87e8d8bef9SDimitry Andric StringRef XCOFF::getNameForTracebackTableLanguageId(
88e8d8bef9SDimitry Andric     XCOFF::TracebackTable::LanguageID LangId) {
89e8d8bef9SDimitry Andric   switch (LangId) {
90e8d8bef9SDimitry Andric     LANG_CASE(C)
91e8d8bef9SDimitry Andric     LANG_CASE(Fortran)
92e8d8bef9SDimitry Andric     LANG_CASE(Pascal)
93e8d8bef9SDimitry Andric     LANG_CASE(Ada)
94e8d8bef9SDimitry Andric     LANG_CASE(PL1)
95e8d8bef9SDimitry Andric     LANG_CASE(Basic)
96e8d8bef9SDimitry Andric     LANG_CASE(Lisp)
97e8d8bef9SDimitry Andric     LANG_CASE(Cobol)
98e8d8bef9SDimitry Andric     LANG_CASE(Modula2)
99e8d8bef9SDimitry Andric     LANG_CASE(Rpg)
100e8d8bef9SDimitry Andric     LANG_CASE(PL8)
101e8d8bef9SDimitry Andric     LANG_CASE(Assembly)
102e8d8bef9SDimitry Andric     LANG_CASE(Java)
103e8d8bef9SDimitry Andric     LANG_CASE(ObjectiveC)
104e8d8bef9SDimitry Andric     LANG_CASE(CPlusPlus)
105e8d8bef9SDimitry Andric   }
106e8d8bef9SDimitry Andric   return "Unknown";
107e8d8bef9SDimitry Andric }
108e8d8bef9SDimitry Andric #undef LANG_CASE
109e8d8bef9SDimitry Andric 
parseParmsType(uint32_t Value,unsigned FixedParmsNum,unsigned FloatingParmsNum)110*fe6060f1SDimitry Andric Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value,
111*fe6060f1SDimitry Andric                                                 unsigned FixedParmsNum,
112*fe6060f1SDimitry Andric                                                 unsigned FloatingParmsNum) {
113e8d8bef9SDimitry Andric   SmallString<32> ParmsType;
114*fe6060f1SDimitry Andric   int Bits = 0;
115*fe6060f1SDimitry Andric   unsigned ParsedFixedNum = 0;
116*fe6060f1SDimitry Andric   unsigned ParsedFloatingNum = 0;
117*fe6060f1SDimitry Andric   unsigned ParsedNum = 0;
118*fe6060f1SDimitry Andric   unsigned ParmsNum = FixedParmsNum + FloatingParmsNum;
119*fe6060f1SDimitry Andric 
120*fe6060f1SDimitry Andric   // In the function PPCFunctionInfo::getParmsType(), when there are no vector
121*fe6060f1SDimitry Andric   // parameters, the 31st bit of ParmsType is always zero even if it indicates a
122*fe6060f1SDimitry Andric   // floating point parameter. The parameter type information is lost. There
123*fe6060f1SDimitry Andric   // are only 8 GPRs used for parameters passing, the floating parameters
124*fe6060f1SDimitry Andric   // also occupy GPRs if there are available, so the 31st bit can never be a
125*fe6060f1SDimitry Andric   // fixed parameter. At the same time, we also do not know whether the zero of
126*fe6060f1SDimitry Andric   // the 31st bit indicates a float or double parameter type here. Therefore, we
127*fe6060f1SDimitry Andric   // ignore the 31st bit.
128*fe6060f1SDimitry Andric   while (Bits < 31 && ParsedNum < ParmsNum) {
129*fe6060f1SDimitry Andric     if (++ParsedNum > 1)
130e8d8bef9SDimitry Andric       ParmsType += ", ";
131e8d8bef9SDimitry Andric     if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) {
132e8d8bef9SDimitry Andric       // Fixed parameter type.
133e8d8bef9SDimitry Andric       ParmsType += "i";
134*fe6060f1SDimitry Andric       ++ParsedFixedNum;
135e8d8bef9SDimitry Andric       Value <<= 1;
136*fe6060f1SDimitry Andric       ++Bits;
137e8d8bef9SDimitry Andric     } else {
138e8d8bef9SDimitry Andric       if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0)
139e8d8bef9SDimitry Andric         // Float parameter type.
140e8d8bef9SDimitry Andric         ParmsType += "f";
141e8d8bef9SDimitry Andric       else
142e8d8bef9SDimitry Andric         // Double parameter type.
143e8d8bef9SDimitry Andric         ParmsType += "d";
144*fe6060f1SDimitry Andric       ++ParsedFloatingNum;
145e8d8bef9SDimitry Andric       Value <<= 2;
146*fe6060f1SDimitry Andric       Bits += 2;
147e8d8bef9SDimitry Andric     }
148e8d8bef9SDimitry Andric   }
149*fe6060f1SDimitry Andric 
150*fe6060f1SDimitry Andric   // We have more parameters than the 32 Bits could encode.
151*fe6060f1SDimitry Andric   if (ParsedNum < ParmsNum)
152*fe6060f1SDimitry Andric     ParmsType += ", ...";
153*fe6060f1SDimitry Andric 
154*fe6060f1SDimitry Andric   if (Value != 0u || ParsedFixedNum > FixedParmsNum ||
155*fe6060f1SDimitry Andric       ParsedFloatingNum > FloatingParmsNum)
156*fe6060f1SDimitry Andric     return createStringError(errc::invalid_argument,
157*fe6060f1SDimitry Andric                              "ParmsType encodes can not map to ParmsNum "
158*fe6060f1SDimitry Andric                              "parameters in parseParmsType.");
159e8d8bef9SDimitry Andric   return ParmsType;
160e8d8bef9SDimitry Andric }
161e8d8bef9SDimitry Andric 
getExtendedTBTableFlagString(uint8_t Flag)162e8d8bef9SDimitry Andric SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) {
163e8d8bef9SDimitry Andric   SmallString<32> Res;
164e8d8bef9SDimitry Andric 
165e8d8bef9SDimitry Andric   if (Flag & ExtendedTBTableFlag::TB_OS1)
166e8d8bef9SDimitry Andric     Res += "TB_OS1 ";
167e8d8bef9SDimitry Andric   if (Flag & ExtendedTBTableFlag::TB_RESERVED)
168e8d8bef9SDimitry Andric     Res += "TB_RESERVED ";
169e8d8bef9SDimitry Andric   if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY)
170e8d8bef9SDimitry Andric     Res += "TB_SSP_CANARY ";
171e8d8bef9SDimitry Andric   if (Flag & ExtendedTBTableFlag::TB_OS2)
172e8d8bef9SDimitry Andric     Res += "TB_OS2 ";
173e8d8bef9SDimitry Andric   if (Flag & ExtendedTBTableFlag::TB_EH_INFO)
174e8d8bef9SDimitry Andric     Res += "TB_EH_INFO ";
175e8d8bef9SDimitry Andric   if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2)
176e8d8bef9SDimitry Andric     Res += "TB_LONGTBTABLE2 ";
177e8d8bef9SDimitry Andric 
178e8d8bef9SDimitry Andric   // Two of the bits that haven't got used in the mask.
179e8d8bef9SDimitry Andric   if (Flag & 0x06)
180e8d8bef9SDimitry Andric     Res += "Unknown ";
181e8d8bef9SDimitry Andric 
182e8d8bef9SDimitry Andric   // Pop the last space.
183e8d8bef9SDimitry Andric   Res.pop_back();
184e8d8bef9SDimitry Andric   return Res;
185e8d8bef9SDimitry Andric }
186e8d8bef9SDimitry Andric 
187*fe6060f1SDimitry Andric Expected<SmallString<32>>
parseParmsTypeWithVecInfo(uint32_t Value,unsigned FixedParmsNum,unsigned FloatingParmsNum,unsigned VectorParmsNum)188*fe6060f1SDimitry Andric XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum,
189*fe6060f1SDimitry Andric                                  unsigned FloatingParmsNum,
190*fe6060f1SDimitry Andric                                  unsigned VectorParmsNum) {
191*fe6060f1SDimitry Andric   SmallString<32> ParmsType;
192*fe6060f1SDimitry Andric 
193*fe6060f1SDimitry Andric   unsigned ParsedFixedNum = 0;
194*fe6060f1SDimitry Andric   unsigned ParsedFloatingNum = 0;
195*fe6060f1SDimitry Andric   unsigned ParsedVectorNum = 0;
196*fe6060f1SDimitry Andric   unsigned ParsedNum = 0;
197*fe6060f1SDimitry Andric   unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum;
198*fe6060f1SDimitry Andric 
199*fe6060f1SDimitry Andric   for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) {
200*fe6060f1SDimitry Andric     if (++ParsedNum > 1)
201*fe6060f1SDimitry Andric       ParmsType += ", ";
202*fe6060f1SDimitry Andric 
203*fe6060f1SDimitry Andric     switch (Value & TracebackTable::ParmTypeMask) {
204*fe6060f1SDimitry Andric     case TracebackTable::ParmTypeIsFixedBits:
205*fe6060f1SDimitry Andric       ParmsType += "i";
206*fe6060f1SDimitry Andric       ++ParsedFixedNum;
207*fe6060f1SDimitry Andric       break;
208*fe6060f1SDimitry Andric     case TracebackTable::ParmTypeIsVectorBits:
209*fe6060f1SDimitry Andric       ParmsType += "v";
210*fe6060f1SDimitry Andric       ++ParsedVectorNum;
211*fe6060f1SDimitry Andric       break;
212*fe6060f1SDimitry Andric     case TracebackTable::ParmTypeIsFloatingBits:
213*fe6060f1SDimitry Andric       ParmsType += "f";
214*fe6060f1SDimitry Andric       ++ParsedFloatingNum;
215*fe6060f1SDimitry Andric       break;
216*fe6060f1SDimitry Andric     case TracebackTable::ParmTypeIsDoubleBits:
217*fe6060f1SDimitry Andric       ParmsType += "d";
218*fe6060f1SDimitry Andric       ++ParsedFloatingNum;
219*fe6060f1SDimitry Andric       break;
220*fe6060f1SDimitry Andric     default:
221*fe6060f1SDimitry Andric       assert(false && "Unrecognized bits in ParmsType.");
222*fe6060f1SDimitry Andric     }
223*fe6060f1SDimitry Andric     Value <<= 2;
224*fe6060f1SDimitry Andric   }
225*fe6060f1SDimitry Andric 
226*fe6060f1SDimitry Andric   // We have more parameters than the 32 Bits could encode.
227*fe6060f1SDimitry Andric   if (ParsedNum < ParmsNum)
228*fe6060f1SDimitry Andric     ParmsType += ", ...";
229*fe6060f1SDimitry Andric 
230*fe6060f1SDimitry Andric   if (Value != 0u || ParsedFixedNum > FixedParmsNum ||
231*fe6060f1SDimitry Andric       ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum)
232*fe6060f1SDimitry Andric     return createStringError(
233*fe6060f1SDimitry Andric         errc::invalid_argument,
234*fe6060f1SDimitry Andric         "ParmsType encodes can not map to ParmsNum parameters "
235*fe6060f1SDimitry Andric         "in parseParmsTypeWithVecInfo.");
236*fe6060f1SDimitry Andric 
237*fe6060f1SDimitry Andric   return ParmsType;
238*fe6060f1SDimitry Andric }
239*fe6060f1SDimitry Andric 
parseVectorParmsType(uint32_t Value,unsigned ParmsNum)240*fe6060f1SDimitry Andric Expected<SmallString<32>> XCOFF::parseVectorParmsType(uint32_t Value,
241*fe6060f1SDimitry Andric                                                       unsigned ParmsNum) {
242*fe6060f1SDimitry Andric   SmallString<32> ParmsType;
243*fe6060f1SDimitry Andric   unsigned ParsedNum = 0;
244*fe6060f1SDimitry Andric   for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) {
245*fe6060f1SDimitry Andric     if (++ParsedNum > 1)
246*fe6060f1SDimitry Andric       ParmsType += ", ";
247*fe6060f1SDimitry Andric     switch (Value & TracebackTable::ParmTypeMask) {
248*fe6060f1SDimitry Andric     case TracebackTable::ParmTypeIsVectorCharBit:
249*fe6060f1SDimitry Andric       ParmsType += "vc";
250*fe6060f1SDimitry Andric       break;
251*fe6060f1SDimitry Andric 
252*fe6060f1SDimitry Andric     case TracebackTable::ParmTypeIsVectorShortBit:
253*fe6060f1SDimitry Andric       ParmsType += "vs";
254*fe6060f1SDimitry Andric       break;
255*fe6060f1SDimitry Andric 
256*fe6060f1SDimitry Andric     case TracebackTable::ParmTypeIsVectorIntBit:
257*fe6060f1SDimitry Andric       ParmsType += "vi";
258*fe6060f1SDimitry Andric       break;
259*fe6060f1SDimitry Andric 
260*fe6060f1SDimitry Andric     case TracebackTable::ParmTypeIsVectorFloatBit:
261*fe6060f1SDimitry Andric       ParmsType += "vf";
262*fe6060f1SDimitry Andric       break;
263*fe6060f1SDimitry Andric     }
264*fe6060f1SDimitry Andric 
265*fe6060f1SDimitry Andric     Value <<= 2;
266*fe6060f1SDimitry Andric   }
267*fe6060f1SDimitry Andric 
268*fe6060f1SDimitry Andric   // We have more parameters than the 32 Bits could encode.
269*fe6060f1SDimitry Andric   if (ParsedNum < ParmsNum)
270*fe6060f1SDimitry Andric     ParmsType += ", ...";
271*fe6060f1SDimitry Andric 
272*fe6060f1SDimitry Andric   if (Value != 0u)
273*fe6060f1SDimitry Andric     return createStringError(errc::invalid_argument,
274*fe6060f1SDimitry Andric                              "ParmsType encodes more than ParmsNum parameters "
275*fe6060f1SDimitry Andric                              "in parseVectorParmsType.");
276*fe6060f1SDimitry Andric   return ParmsType;
277*fe6060f1SDimitry Andric }
278