xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- XCOFFDump.cpp - XCOFF-specific dumper -----------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric ///
95ffd83dbSDimitry Andric /// \file
105ffd83dbSDimitry Andric /// This file implements the XCOFF-specific dumper for llvm-objdump.
115ffd83dbSDimitry Andric ///
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "XCOFFDump.h"
155ffd83dbSDimitry Andric 
165ffd83dbSDimitry Andric #include "llvm-objdump.h"
17*06c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
185ffd83dbSDimitry Andric #include "llvm/Demangle/Demangle.h"
19*06c3fb27SDimitry Andric #include "llvm/MC/MCInstPrinter.h"
20*06c3fb27SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
21*06c3fb27SDimitry Andric #include "llvm/Support/Casting.h"
22*06c3fb27SDimitry Andric #include "llvm/Support/Endian.h"
23*06c3fb27SDimitry Andric #include "llvm/Support/FormattedStream.h"
24*06c3fb27SDimitry Andric #include <algorithm>
255ffd83dbSDimitry Andric 
265ffd83dbSDimitry Andric using namespace llvm;
275ffd83dbSDimitry Andric using namespace llvm::object;
28*06c3fb27SDimitry Andric using namespace llvm::XCOFF;
29*06c3fb27SDimitry Andric using namespace llvm::support;
30*06c3fb27SDimitry Andric 
31*06c3fb27SDimitry Andric namespace {
32*06c3fb27SDimitry Andric class XCOFFDumper : public objdump::Dumper {
33*06c3fb27SDimitry Andric public:
34*06c3fb27SDimitry Andric   XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O) {}
35*06c3fb27SDimitry Andric   void printPrivateHeaders(bool MachOOnlyFirst) override;
36*06c3fb27SDimitry Andric };
37*06c3fb27SDimitry Andric } // namespace
38*06c3fb27SDimitry Andric 
39*06c3fb27SDimitry Andric std::unique_ptr<objdump::Dumper>
40*06c3fb27SDimitry Andric objdump::createXCOFFDumper(const object::XCOFFObjectFile &Obj) {
41*06c3fb27SDimitry Andric   return std::make_unique<XCOFFDumper>(Obj);
42*06c3fb27SDimitry Andric }
43*06c3fb27SDimitry Andric 
44*06c3fb27SDimitry Andric void XCOFFDumper::printPrivateHeaders(bool) {}
455ffd83dbSDimitry Andric 
46753f127fSDimitry Andric Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile &Obj,
475ffd83dbSDimitry Andric                                              const RelocationRef &Rel,
485ffd83dbSDimitry Andric                                              SmallVectorImpl<char> &Result) {
495ffd83dbSDimitry Andric   symbol_iterator SymI = Rel.getSymbol();
50753f127fSDimitry Andric   if (SymI == Obj.symbol_end())
515ffd83dbSDimitry Andric     return make_error<GenericBinaryError>(
525ffd83dbSDimitry Andric         "invalid symbol reference in relocation entry",
535ffd83dbSDimitry Andric         object_error::parse_failed);
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric   Expected<StringRef> SymNameOrErr = SymI->getName();
565ffd83dbSDimitry Andric   if (!SymNameOrErr)
575ffd83dbSDimitry Andric     return SymNameOrErr.takeError();
585ffd83dbSDimitry Andric 
59*06c3fb27SDimitry Andric   std::string SymName =
60*06c3fb27SDimitry Andric       Demangle ? demangle(*SymNameOrErr) : SymNameOrErr->str();
615ffd83dbSDimitry Andric   if (SymbolDescription)
625ffd83dbSDimitry Andric     SymName = getXCOFFSymbolDescription(createSymbolInfo(Obj, *SymI), SymName);
635ffd83dbSDimitry Andric 
645ffd83dbSDimitry Andric   Result.append(SymName.begin(), SymName.end());
655ffd83dbSDimitry Andric   return Error::success();
665ffd83dbSDimitry Andric }
675ffd83dbSDimitry Andric 
68bdd1243dSDimitry Andric std::optional<XCOFF::StorageMappingClass>
69753f127fSDimitry Andric objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile &Obj,
705ffd83dbSDimitry Andric                                 const SymbolRef &Sym) {
71753f127fSDimitry Andric   const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());
725ffd83dbSDimitry Andric 
73fe6060f1SDimitry Andric   if (!SymRef.isCsectSymbol())
74bdd1243dSDimitry Andric     return std::nullopt;
75fe6060f1SDimitry Andric 
76fe6060f1SDimitry Andric   auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
77fe6060f1SDimitry Andric   if (!CsectAuxEntOrErr)
78bdd1243dSDimitry Andric     return std::nullopt;
79fe6060f1SDimitry Andric 
80fe6060f1SDimitry Andric   return CsectAuxEntOrErr.get().getStorageMappingClass();
815ffd83dbSDimitry Andric }
825ffd83dbSDimitry Andric 
83bdd1243dSDimitry Andric std::optional<object::SymbolRef>
84753f127fSDimitry Andric objdump::getXCOFFSymbolContainingSymbolRef(const XCOFFObjectFile &Obj,
85349cc55cSDimitry Andric                                            const SymbolRef &Sym) {
86753f127fSDimitry Andric   const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());
87349cc55cSDimitry Andric   if (!SymRef.isCsectSymbol())
88bdd1243dSDimitry Andric     return std::nullopt;
89349cc55cSDimitry Andric 
90349cc55cSDimitry Andric   Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
91349cc55cSDimitry Andric   if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel())
92bdd1243dSDimitry Andric     return std::nullopt;
93349cc55cSDimitry Andric   uint32_t Idx =
94349cc55cSDimitry Andric       static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength());
95349cc55cSDimitry Andric   DataRefImpl DRI;
96753f127fSDimitry Andric   DRI.p = Obj.getSymbolByIndex(Idx);
97753f127fSDimitry Andric   return SymbolRef(DRI, &Obj);
98349cc55cSDimitry Andric }
99349cc55cSDimitry Andric 
100753f127fSDimitry Andric bool objdump::isLabel(const XCOFFObjectFile &Obj, const SymbolRef &Sym) {
101753f127fSDimitry Andric   const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());
102fe6060f1SDimitry Andric   if (!SymRef.isCsectSymbol())
1035ffd83dbSDimitry Andric     return false;
104fe6060f1SDimitry Andric 
105fe6060f1SDimitry Andric   auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
106fe6060f1SDimitry Andric   if (!CsectAuxEntOrErr)
107fe6060f1SDimitry Andric     return false;
108fe6060f1SDimitry Andric 
109fe6060f1SDimitry Andric   return CsectAuxEntOrErr.get().isLabel();
1105ffd83dbSDimitry Andric }
1115ffd83dbSDimitry Andric 
1125ffd83dbSDimitry Andric std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
1135ffd83dbSDimitry Andric                                                StringRef SymbolName) {
1145ffd83dbSDimitry Andric   assert(SymbolInfo.isXCOFF() && "Must be a XCOFFSymInfo.");
1155ffd83dbSDimitry Andric 
1165ffd83dbSDimitry Andric   std::string Result;
1175ffd83dbSDimitry Andric   // Dummy symbols have no symbol index.
1185ffd83dbSDimitry Andric   if (SymbolInfo.XCOFFSymInfo.Index)
119bdd1243dSDimitry Andric     Result =
120bdd1243dSDimitry Andric         ("(idx: " + Twine(*SymbolInfo.XCOFFSymInfo.Index) + ") " + SymbolName)
1215ffd83dbSDimitry Andric             .str();
1225ffd83dbSDimitry Andric   else
1235ffd83dbSDimitry Andric     Result.append(SymbolName.begin(), SymbolName.end());
1245ffd83dbSDimitry Andric 
1255ffd83dbSDimitry Andric   if (SymbolInfo.XCOFFSymInfo.StorageMappingClass &&
1265ffd83dbSDimitry Andric       !SymbolInfo.XCOFFSymInfo.IsLabel) {
1275ffd83dbSDimitry Andric     const XCOFF::StorageMappingClass Smc =
12881ad6265SDimitry Andric         *SymbolInfo.XCOFFSymInfo.StorageMappingClass;
1295ffd83dbSDimitry Andric     Result.append(("[" + XCOFF::getMappingClassString(Smc) + "]").str());
1305ffd83dbSDimitry Andric   }
1315ffd83dbSDimitry Andric 
1325ffd83dbSDimitry Andric   return Result;
1335ffd83dbSDimitry Andric }
134*06c3fb27SDimitry Andric 
135*06c3fb27SDimitry Andric #define PRINTBOOL(Prefix, Obj, Field)                                          \
136*06c3fb27SDimitry Andric   OS << Prefix << " " << ((Obj.Field()) ? "+" : "-") << #Field
137*06c3fb27SDimitry Andric 
138*06c3fb27SDimitry Andric #define PRINTGET(Prefix, Obj, Field)                                           \
139*06c3fb27SDimitry Andric   OS << Prefix << " " << #Field << " = "                                       \
140*06c3fb27SDimitry Andric      << static_cast<unsigned>(Obj.get##Field())
141*06c3fb27SDimitry Andric 
142*06c3fb27SDimitry Andric #define PRINTOPTIONAL(Field)                                                   \
143*06c3fb27SDimitry Andric   if (TbTable.get##Field()) {                                                  \
144*06c3fb27SDimitry Andric     OS << '\n';                                                                \
145*06c3fb27SDimitry Andric     printRawData(Bytes.slice(Index, 4), Address + Index, OS, STI);             \
146*06c3fb27SDimitry Andric     Index += 4;                                                                \
147*06c3fb27SDimitry Andric     OS << "\t# " << #Field << " = " << *TbTable.get##Field();                  \
148*06c3fb27SDimitry Andric   }
149*06c3fb27SDimitry Andric 
150*06c3fb27SDimitry Andric void objdump::dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address,
151*06c3fb27SDimitry Andric                                  formatted_raw_ostream &OS, uint64_t End,
152*06c3fb27SDimitry Andric                                  const MCSubtargetInfo &STI,
153*06c3fb27SDimitry Andric                                  const XCOFFObjectFile *Obj) {
154*06c3fb27SDimitry Andric   uint64_t Index = 0;
155*06c3fb27SDimitry Andric   unsigned TabStop = getInstStartColumn(STI) - 1;
156*06c3fb27SDimitry Andric   // Print traceback table boundary.
157*06c3fb27SDimitry Andric   printRawData(Bytes.slice(Index, 4), Address, OS, STI);
158*06c3fb27SDimitry Andric   OS << "\t# Traceback table start\n";
159*06c3fb27SDimitry Andric   Index += 4;
160*06c3fb27SDimitry Andric 
161*06c3fb27SDimitry Andric   uint64_t Size = End - Address;
162*06c3fb27SDimitry Andric   bool Is64Bit = Obj->is64Bit();
163*06c3fb27SDimitry Andric 
164*06c3fb27SDimitry Andric   // XCOFFTracebackTable::create modifies the size parameter, so ensure Size
165*06c3fb27SDimitry Andric   // isn't changed.
166*06c3fb27SDimitry Andric   uint64_t SizeCopy = End - Address;
167*06c3fb27SDimitry Andric   Expected<XCOFFTracebackTable> TTOrErr =
168*06c3fb27SDimitry Andric       XCOFFTracebackTable::create(Bytes.data() + Index, SizeCopy, Is64Bit);
169*06c3fb27SDimitry Andric 
170*06c3fb27SDimitry Andric   if (!TTOrErr) {
171*06c3fb27SDimitry Andric     std::string WarningMsgStr;
172*06c3fb27SDimitry Andric     raw_string_ostream WarningStream(WarningMsgStr);
173*06c3fb27SDimitry Andric     WarningStream << "failure parsing traceback table with address: 0x"
174*06c3fb27SDimitry Andric                   << utohexstr(Address) + "\n>>> "
175*06c3fb27SDimitry Andric                   << toString(TTOrErr.takeError())
176*06c3fb27SDimitry Andric                   << "\n>>> Raw traceback table data is:\n";
177*06c3fb27SDimitry Andric 
178*06c3fb27SDimitry Andric     uint64_t LastNonZero = Index;
179*06c3fb27SDimitry Andric     for (uint64_t I = Index; I < Size; I += 4)
180*06c3fb27SDimitry Andric       if (support::endian::read32be(Bytes.slice(I, 4).data()) != 0)
181*06c3fb27SDimitry Andric         LastNonZero = I + 4 > Size ? Size : I + 4;
182*06c3fb27SDimitry Andric 
183*06c3fb27SDimitry Andric     if (Size - LastNonZero <= 4)
184*06c3fb27SDimitry Andric       LastNonZero = Size;
185*06c3fb27SDimitry Andric 
186*06c3fb27SDimitry Andric     formatted_raw_ostream FOS(WarningStream);
187*06c3fb27SDimitry Andric     while (Index < LastNonZero) {
188*06c3fb27SDimitry Andric       printRawData(Bytes.slice(Index, 4), Address + Index, FOS, STI);
189*06c3fb27SDimitry Andric       Index += 4;
190*06c3fb27SDimitry Andric       WarningStream << '\n';
191*06c3fb27SDimitry Andric     }
192*06c3fb27SDimitry Andric 
193*06c3fb27SDimitry Andric     // Print all remaining zeroes as ...
194*06c3fb27SDimitry Andric     if (Size - LastNonZero >= 8)
195*06c3fb27SDimitry Andric       WarningStream << "\t\t...\n";
196*06c3fb27SDimitry Andric 
197*06c3fb27SDimitry Andric     reportWarning(WarningMsgStr, Obj->getFileName());
198*06c3fb27SDimitry Andric     return;
199*06c3fb27SDimitry Andric   }
200*06c3fb27SDimitry Andric 
201*06c3fb27SDimitry Andric   auto PrintBytes = [&](uint64_t N) {
202*06c3fb27SDimitry Andric     printRawData(Bytes.slice(Index, N), Address + Index, OS, STI);
203*06c3fb27SDimitry Andric     Index += N;
204*06c3fb27SDimitry Andric   };
205*06c3fb27SDimitry Andric 
206*06c3fb27SDimitry Andric   XCOFFTracebackTable TbTable = *TTOrErr;
207*06c3fb27SDimitry Andric   // Print the first of the 8 bytes of mandatory fields.
208*06c3fb27SDimitry Andric   PrintBytes(1);
209*06c3fb27SDimitry Andric   OS << format("\t# Version = %i", TbTable.getVersion()) << '\n';
210*06c3fb27SDimitry Andric 
211*06c3fb27SDimitry Andric   // Print the second of the 8 bytes of mandatory fields.
212*06c3fb27SDimitry Andric   PrintBytes(1);
213*06c3fb27SDimitry Andric   TracebackTable::LanguageID LangId =
214*06c3fb27SDimitry Andric       static_cast<TracebackTable::LanguageID>(TbTable.getLanguageID());
215*06c3fb27SDimitry Andric   OS << "\t# Language = " << getNameForTracebackTableLanguageId(LangId) << '\n';
216*06c3fb27SDimitry Andric 
217*06c3fb27SDimitry Andric   auto Split = [&]() {
218*06c3fb27SDimitry Andric     OS << '\n';
219*06c3fb27SDimitry Andric     OS.indent(TabStop);
220*06c3fb27SDimitry Andric   };
221*06c3fb27SDimitry Andric 
222*06c3fb27SDimitry Andric   // Print the third of the 8 bytes of mandatory fields.
223*06c3fb27SDimitry Andric   PrintBytes(1);
224*06c3fb27SDimitry Andric   PRINTBOOL("\t#", TbTable, isGlobalLinkage);
225*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isOutOfLineEpilogOrPrologue);
226*06c3fb27SDimitry Andric   Split();
227*06c3fb27SDimitry Andric   PRINTBOOL("\t ", TbTable, hasTraceBackTableOffset);
228*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isInternalProcedure);
229*06c3fb27SDimitry Andric   Split();
230*06c3fb27SDimitry Andric   PRINTBOOL("\t ", TbTable, hasControlledStorage);
231*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isTOCless);
232*06c3fb27SDimitry Andric   Split();
233*06c3fb27SDimitry Andric   PRINTBOOL("\t ", TbTable, isFloatingPointPresent);
234*06c3fb27SDimitry Andric   Split();
235*06c3fb27SDimitry Andric   PRINTBOOL("\t ", TbTable, isFloatingPointOperationLogOrAbortEnabled);
236*06c3fb27SDimitry Andric   OS << '\n';
237*06c3fb27SDimitry Andric 
238*06c3fb27SDimitry Andric   // Print the 4th of the 8 bytes of mandatory fields.
239*06c3fb27SDimitry Andric   PrintBytes(1);
240*06c3fb27SDimitry Andric   PRINTBOOL("\t#", TbTable, isInterruptHandler);
241*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isFuncNamePresent);
242*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isAllocaUsed);
243*06c3fb27SDimitry Andric   Split();
244*06c3fb27SDimitry Andric   PRINTGET("\t ", TbTable, OnConditionDirective);
245*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isCRSaved);
246*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isLRSaved);
247*06c3fb27SDimitry Andric   OS << '\n';
248*06c3fb27SDimitry Andric 
249*06c3fb27SDimitry Andric   // Print the 5th of the 8 bytes of mandatory fields.
250*06c3fb27SDimitry Andric   PrintBytes(1);
251*06c3fb27SDimitry Andric   PRINTBOOL("\t#", TbTable, isBackChainStored);
252*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isFixup);
253*06c3fb27SDimitry Andric   PRINTGET(",", TbTable, NumOfFPRsSaved);
254*06c3fb27SDimitry Andric   OS << '\n';
255*06c3fb27SDimitry Andric 
256*06c3fb27SDimitry Andric   // Print the 6th of the 8 bytes of mandatory fields.
257*06c3fb27SDimitry Andric   PrintBytes(1);
258*06c3fb27SDimitry Andric   PRINTBOOL("\t#", TbTable, hasExtensionTable);
259*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, hasVectorInfo);
260*06c3fb27SDimitry Andric   PRINTGET(",", TbTable, NumOfGPRsSaved);
261*06c3fb27SDimitry Andric   OS << '\n';
262*06c3fb27SDimitry Andric 
263*06c3fb27SDimitry Andric   // Print the 7th of the 8 bytes of mandatory fields.
264*06c3fb27SDimitry Andric   PrintBytes(1);
265*06c3fb27SDimitry Andric   PRINTGET("\t#", TbTable, NumberOfFixedParms);
266*06c3fb27SDimitry Andric   OS << '\n';
267*06c3fb27SDimitry Andric 
268*06c3fb27SDimitry Andric   // Print the 8th of the 8 bytes of mandatory fields.
269*06c3fb27SDimitry Andric   PrintBytes(1);
270*06c3fb27SDimitry Andric   PRINTGET("\t#", TbTable, NumberOfFPParms);
271*06c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, hasParmsOnStack);
272*06c3fb27SDimitry Andric 
273*06c3fb27SDimitry Andric   PRINTOPTIONAL(ParmsType);
274*06c3fb27SDimitry Andric   PRINTOPTIONAL(TraceBackTableOffset);
275*06c3fb27SDimitry Andric   PRINTOPTIONAL(HandlerMask);
276*06c3fb27SDimitry Andric   PRINTOPTIONAL(NumOfCtlAnchors);
277*06c3fb27SDimitry Andric 
278*06c3fb27SDimitry Andric   if (TbTable.getControlledStorageInfoDisp()) {
279*06c3fb27SDimitry Andric     SmallVector<uint32_t, 8> Disp = *TbTable.getControlledStorageInfoDisp();
280*06c3fb27SDimitry Andric     for (unsigned I = 0; I < Disp.size(); ++I) {
281*06c3fb27SDimitry Andric       OS << '\n';
282*06c3fb27SDimitry Andric       PrintBytes(4);
283*06c3fb27SDimitry Andric       OS << "\t" << (I ? " " : "#") << " ControlledStorageInfoDisp[" << I
284*06c3fb27SDimitry Andric          << "] = " << Disp[I];
285*06c3fb27SDimitry Andric     }
286*06c3fb27SDimitry Andric   }
287*06c3fb27SDimitry Andric 
288*06c3fb27SDimitry Andric   // If there is a name, print the function name and function name length.
289*06c3fb27SDimitry Andric   if (TbTable.isFuncNamePresent()) {
290*06c3fb27SDimitry Andric     uint16_t FunctionNameLen = TbTable.getFunctionName()->size();
291*06c3fb27SDimitry Andric     if (FunctionNameLen == 0) {
292*06c3fb27SDimitry Andric       OS << '\n';
293*06c3fb27SDimitry Andric       reportWarning(
294*06c3fb27SDimitry Andric           "the length of the function name must be greater than zero if the "
295*06c3fb27SDimitry Andric           "isFuncNamePresent bit is set in the traceback table",
296*06c3fb27SDimitry Andric           Obj->getFileName());
297*06c3fb27SDimitry Andric       return;
298*06c3fb27SDimitry Andric     }
299*06c3fb27SDimitry Andric 
300*06c3fb27SDimitry Andric     OS << '\n';
301*06c3fb27SDimitry Andric     PrintBytes(2);
302*06c3fb27SDimitry Andric     OS << "\t# FunctionNameLen = " << FunctionNameLen;
303*06c3fb27SDimitry Andric 
304*06c3fb27SDimitry Andric     uint16_t RemainingBytes = FunctionNameLen;
305*06c3fb27SDimitry Andric     bool HasPrinted = false;
306*06c3fb27SDimitry Andric     while (RemainingBytes > 0) {
307*06c3fb27SDimitry Andric       OS << '\n';
308*06c3fb27SDimitry Andric       uint16_t PrintLen = RemainingBytes >= 4 ? 4 : RemainingBytes;
309*06c3fb27SDimitry Andric       printRawData(Bytes.slice(Index, PrintLen), Address + Index, OS, STI);
310*06c3fb27SDimitry Andric       Index += PrintLen;
311*06c3fb27SDimitry Andric       RemainingBytes -= PrintLen;
312*06c3fb27SDimitry Andric 
313*06c3fb27SDimitry Andric       if (!HasPrinted) {
314*06c3fb27SDimitry Andric         OS << "\t# FunctionName = " << *TbTable.getFunctionName();
315*06c3fb27SDimitry Andric         HasPrinted = true;
316*06c3fb27SDimitry Andric       }
317*06c3fb27SDimitry Andric     }
318*06c3fb27SDimitry Andric   }
319*06c3fb27SDimitry Andric 
320*06c3fb27SDimitry Andric   if (TbTable.isAllocaUsed()) {
321*06c3fb27SDimitry Andric     OS << '\n';
322*06c3fb27SDimitry Andric     PrintBytes(1);
323*06c3fb27SDimitry Andric     OS << format("\t# AllocaRegister = %u", *TbTable.getAllocaRegister());
324*06c3fb27SDimitry Andric   }
325*06c3fb27SDimitry Andric 
326*06c3fb27SDimitry Andric   if (TbTable.getVectorExt()) {
327*06c3fb27SDimitry Andric     OS << '\n';
328*06c3fb27SDimitry Andric     TBVectorExt VecExt = *TbTable.getVectorExt();
329*06c3fb27SDimitry Andric     // Print first byte of VectorExt.
330*06c3fb27SDimitry Andric     PrintBytes(1);
331*06c3fb27SDimitry Andric     PRINTGET("\t#", VecExt, NumberOfVRSaved);
332*06c3fb27SDimitry Andric     PRINTBOOL(",", VecExt, isVRSavedOnStack);
333*06c3fb27SDimitry Andric     PRINTBOOL(",", VecExt, hasVarArgs);
334*06c3fb27SDimitry Andric     OS << '\n';
335*06c3fb27SDimitry Andric 
336*06c3fb27SDimitry Andric     // Print the second byte of VectorExt.
337*06c3fb27SDimitry Andric     PrintBytes(1);
338*06c3fb27SDimitry Andric     PRINTGET("\t#", VecExt, NumberOfVectorParms);
339*06c3fb27SDimitry Andric     PRINTBOOL(",", VecExt, hasVMXInstruction);
340*06c3fb27SDimitry Andric     OS << '\n';
341*06c3fb27SDimitry Andric 
342*06c3fb27SDimitry Andric     PrintBytes(4);
343*06c3fb27SDimitry Andric     OS << "\t# VectorParmsInfoString = " << VecExt.getVectorParmsInfo();
344*06c3fb27SDimitry Andric 
345*06c3fb27SDimitry Andric     // There are two bytes of padding after vector info.
346*06c3fb27SDimitry Andric     OS << '\n';
347*06c3fb27SDimitry Andric     PrintBytes(2);
348*06c3fb27SDimitry Andric     OS << "\t# Padding";
349*06c3fb27SDimitry Andric   }
350*06c3fb27SDimitry Andric 
351*06c3fb27SDimitry Andric   if (TbTable.getExtensionTable()) {
352*06c3fb27SDimitry Andric     OS << '\n';
353*06c3fb27SDimitry Andric     PrintBytes(1);
354*06c3fb27SDimitry Andric     ExtendedTBTableFlag Flag =
355*06c3fb27SDimitry Andric         static_cast<ExtendedTBTableFlag>(*TbTable.getExtensionTable());
356*06c3fb27SDimitry Andric     OS << "\t# ExtensionTable = " << getExtendedTBTableFlagString(Flag);
357*06c3fb27SDimitry Andric   }
358*06c3fb27SDimitry Andric 
359*06c3fb27SDimitry Andric   if (TbTable.getEhInfoDisp()) {
360*06c3fb27SDimitry Andric     // There are 4 bytes alignment before eh info displacement.
361*06c3fb27SDimitry Andric     if (Index % 4) {
362*06c3fb27SDimitry Andric       OS << '\n';
363*06c3fb27SDimitry Andric       PrintBytes(4 - Index % 4);
364*06c3fb27SDimitry Andric       OS << "\t# Alignment padding for eh info displacement";
365*06c3fb27SDimitry Andric     }
366*06c3fb27SDimitry Andric     OS << '\n';
367*06c3fb27SDimitry Andric     // The size of the displacement (address) is 4 bytes in 32-bit object files,
368*06c3fb27SDimitry Andric     // and 8 bytes in 64-bit object files.
369*06c3fb27SDimitry Andric     PrintBytes(4);
370*06c3fb27SDimitry Andric     OS << "\t# EH info displacement";
371*06c3fb27SDimitry Andric     if (Is64Bit) {
372*06c3fb27SDimitry Andric       OS << '\n';
373*06c3fb27SDimitry Andric       PrintBytes(4);
374*06c3fb27SDimitry Andric     }
375*06c3fb27SDimitry Andric   }
376*06c3fb27SDimitry Andric 
377*06c3fb27SDimitry Andric   OS << '\n';
378*06c3fb27SDimitry Andric   if (End == Address + Index)
379*06c3fb27SDimitry Andric     return;
380*06c3fb27SDimitry Andric 
381*06c3fb27SDimitry Andric   Size = End - Address;
382*06c3fb27SDimitry Andric 
383*06c3fb27SDimitry Andric   const char *LineSuffix = "\t# Padding\n";
384*06c3fb27SDimitry Andric   auto IsWordZero = [&](uint64_t WordPos) {
385*06c3fb27SDimitry Andric     if (WordPos >= Size)
386*06c3fb27SDimitry Andric       return false;
387*06c3fb27SDimitry Andric     uint64_t LineLength = std::min(4 - WordPos % 4, Size - WordPos);
388*06c3fb27SDimitry Andric     return std::all_of(Bytes.begin() + WordPos,
389*06c3fb27SDimitry Andric                        Bytes.begin() + WordPos + LineLength,
390*06c3fb27SDimitry Andric                        [](uint8_t Byte) { return Byte == 0; });
391*06c3fb27SDimitry Andric   };
392*06c3fb27SDimitry Andric 
393*06c3fb27SDimitry Andric   bool AreWordsZero[] = {IsWordZero(Index), IsWordZero(alignTo(Index, 4) + 4),
394*06c3fb27SDimitry Andric                          IsWordZero(alignTo(Index, 4) + 8)};
395*06c3fb27SDimitry Andric   bool ShouldPrintLine = true;
396*06c3fb27SDimitry Andric   while (true) {
397*06c3fb27SDimitry Andric     // Determine the length of the line (4, except for the first line, which
398*06c3fb27SDimitry Andric     // will be just enough to align to the word boundary, and the last line,
399*06c3fb27SDimitry Andric     // which will be the remainder of the data).
400*06c3fb27SDimitry Andric     uint64_t LineLength = std::min(4 - Index % 4, Size - Index);
401*06c3fb27SDimitry Andric     if (ShouldPrintLine) {
402*06c3fb27SDimitry Andric       // Print the line.
403*06c3fb27SDimitry Andric       printRawData(Bytes.slice(Index, LineLength), Address + Index, OS, STI);
404*06c3fb27SDimitry Andric       OS << LineSuffix;
405*06c3fb27SDimitry Andric       LineSuffix = "\n";
406*06c3fb27SDimitry Andric     }
407*06c3fb27SDimitry Andric 
408*06c3fb27SDimitry Andric     Index += LineLength;
409*06c3fb27SDimitry Andric     if (Index == Size)
410*06c3fb27SDimitry Andric       return;
411*06c3fb27SDimitry Andric 
412*06c3fb27SDimitry Andric     // For 3 or more consecutive lines of zeros, skip all but the first one, and
413*06c3fb27SDimitry Andric     // replace them with "...".
414*06c3fb27SDimitry Andric     if (AreWordsZero[0] && AreWordsZero[1] && AreWordsZero[2]) {
415*06c3fb27SDimitry Andric       if (ShouldPrintLine)
416*06c3fb27SDimitry Andric         OS << std::string(8, ' ') << "...\n";
417*06c3fb27SDimitry Andric       ShouldPrintLine = false;
418*06c3fb27SDimitry Andric     } else if (!AreWordsZero[1]) {
419*06c3fb27SDimitry Andric       // We have reached the end of a skipped block of zeros.
420*06c3fb27SDimitry Andric       ShouldPrintLine = true;
421*06c3fb27SDimitry Andric     }
422*06c3fb27SDimitry Andric     AreWordsZero[0] = AreWordsZero[1];
423*06c3fb27SDimitry Andric     AreWordsZero[1] = AreWordsZero[2];
424*06c3fb27SDimitry Andric     AreWordsZero[2] = IsWordZero(Index + 8);
425*06c3fb27SDimitry Andric   }
426*06c3fb27SDimitry Andric }
427*06c3fb27SDimitry Andric #undef PRINTBOOL
428*06c3fb27SDimitry Andric #undef PRINTGET
429*06c3fb27SDimitry Andric #undef PRINTOPTIONAL
430