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