xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric //
9*06c3fb27SDimitry Andric // Implementation of the GOFFObjectFile class.
10*06c3fb27SDimitry Andric //
11*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
12*06c3fb27SDimitry Andric 
13*06c3fb27SDimitry Andric #include "llvm/Object/GOFFObjectFile.h"
14*06c3fb27SDimitry Andric #include "llvm/BinaryFormat/GOFF.h"
15*06c3fb27SDimitry Andric #include "llvm/Object/GOFF.h"
16*06c3fb27SDimitry Andric #include "llvm/Support/Debug.h"
17*06c3fb27SDimitry Andric #include "llvm/Support/Errc.h"
18*06c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h"
19*06c3fb27SDimitry Andric 
20*06c3fb27SDimitry Andric #ifndef DEBUG_TYPE
21*06c3fb27SDimitry Andric #define DEBUG_TYPE "goff"
22*06c3fb27SDimitry Andric #endif
23*06c3fb27SDimitry Andric 
24*06c3fb27SDimitry Andric using namespace llvm::object;
25*06c3fb27SDimitry Andric using namespace llvm;
26*06c3fb27SDimitry Andric 
27*06c3fb27SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
28*06c3fb27SDimitry Andric ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) {
29*06c3fb27SDimitry Andric   Error Err = Error::success();
30*06c3fb27SDimitry Andric   std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err));
31*06c3fb27SDimitry Andric   if (Err)
32*06c3fb27SDimitry Andric     return std::move(Err);
33*06c3fb27SDimitry Andric   return std::move(Ret);
34*06c3fb27SDimitry Andric }
35*06c3fb27SDimitry Andric 
36*06c3fb27SDimitry Andric GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
37*06c3fb27SDimitry Andric     : ObjectFile(Binary::ID_GOFF, Object) {
38*06c3fb27SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
39*06c3fb27SDimitry Andric   // Object file isn't the right size, bail out early.
40*06c3fb27SDimitry Andric   if ((Object.getBufferSize() % GOFF::RecordLength) != 0) {
41*06c3fb27SDimitry Andric     Err = createStringError(
42*06c3fb27SDimitry Andric         object_error::unexpected_eof,
43*06c3fb27SDimitry Andric         "object file is not the right size. Must be a multiple "
44*06c3fb27SDimitry Andric         "of 80 bytes, but is " +
45*06c3fb27SDimitry Andric             std::to_string(Object.getBufferSize()) + " bytes");
46*06c3fb27SDimitry Andric     return;
47*06c3fb27SDimitry Andric   }
48*06c3fb27SDimitry Andric   // Object file doesn't start/end with HDR/END records.
49*06c3fb27SDimitry Andric   // Bail out early.
50*06c3fb27SDimitry Andric   if (Object.getBufferSize() != 0) {
51*06c3fb27SDimitry Andric     if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) {
52*06c3fb27SDimitry Andric       Err = createStringError(object_error::parse_failed,
53*06c3fb27SDimitry Andric                               "object file must start with HDR record");
54*06c3fb27SDimitry Andric       return;
55*06c3fb27SDimitry Andric     }
56*06c3fb27SDimitry Andric     if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 !=
57*06c3fb27SDimitry Andric         GOFF::RT_END) {
58*06c3fb27SDimitry Andric       Err = createStringError(object_error::parse_failed,
59*06c3fb27SDimitry Andric                               "object file must end with END record");
60*06c3fb27SDimitry Andric       return;
61*06c3fb27SDimitry Andric     }
62*06c3fb27SDimitry Andric   }
63*06c3fb27SDimitry Andric 
64*06c3fb27SDimitry Andric   SectionEntryImpl DummySection;
65*06c3fb27SDimitry Andric   SectionList.emplace_back(DummySection); // Dummy entry at index 0.
66*06c3fb27SDimitry Andric 
67*06c3fb27SDimitry Andric   uint8_t PrevRecordType = 0;
68*06c3fb27SDimitry Andric   uint8_t PrevContinuationBits = 0;
69*06c3fb27SDimitry Andric   const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd());
70*06c3fb27SDimitry Andric   for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) {
71*06c3fb27SDimitry Andric     uint8_t RecordType = (I[1] & 0xF0) >> 4;
72*06c3fb27SDimitry Andric     bool IsContinuation = I[1] & 0x02;
73*06c3fb27SDimitry Andric     bool PrevWasContinued = PrevContinuationBits & 0x01;
74*06c3fb27SDimitry Andric     size_t RecordNum = (I - base()) / GOFF::RecordLength;
75*06c3fb27SDimitry Andric 
76*06c3fb27SDimitry Andric     // If the previous record was continued, the current record should be a
77*06c3fb27SDimitry Andric     // continuation.
78*06c3fb27SDimitry Andric     if (PrevWasContinued && !IsContinuation) {
79*06c3fb27SDimitry Andric       if (PrevRecordType == RecordType) {
80*06c3fb27SDimitry Andric         Err = createStringError(object_error::parse_failed,
81*06c3fb27SDimitry Andric                                 "record " + std::to_string(RecordNum) +
82*06c3fb27SDimitry Andric                                     " is not a continuation record but the "
83*06c3fb27SDimitry Andric                                     "preceding record is continued");
84*06c3fb27SDimitry Andric         return;
85*06c3fb27SDimitry Andric       }
86*06c3fb27SDimitry Andric     }
87*06c3fb27SDimitry Andric     // Don't parse continuations records, only parse initial record.
88*06c3fb27SDimitry Andric     if (IsContinuation) {
89*06c3fb27SDimitry Andric       if (RecordType != PrevRecordType) {
90*06c3fb27SDimitry Andric         Err = createStringError(object_error::parse_failed,
91*06c3fb27SDimitry Andric                                 "record " + std::to_string(RecordNum) +
92*06c3fb27SDimitry Andric                                     " is a continuation record that does not "
93*06c3fb27SDimitry Andric                                     "match the type of the previous record");
94*06c3fb27SDimitry Andric         return;
95*06c3fb27SDimitry Andric       }
96*06c3fb27SDimitry Andric       if (!PrevWasContinued) {
97*06c3fb27SDimitry Andric         Err = createStringError(object_error::parse_failed,
98*06c3fb27SDimitry Andric                                 "record " + std::to_string(RecordNum) +
99*06c3fb27SDimitry Andric                                     " is a continuation record that is not "
100*06c3fb27SDimitry Andric                                     "preceded by a continued record");
101*06c3fb27SDimitry Andric         return;
102*06c3fb27SDimitry Andric       }
103*06c3fb27SDimitry Andric       PrevRecordType = RecordType;
104*06c3fb27SDimitry Andric       PrevContinuationBits = I[1] & 0x03;
105*06c3fb27SDimitry Andric       continue;
106*06c3fb27SDimitry Andric     }
107*06c3fb27SDimitry Andric 
108*06c3fb27SDimitry Andric #ifndef NDEBUG
109*06c3fb27SDimitry Andric     for (size_t J = 0; J < GOFF::RecordLength; ++J) {
110*06c3fb27SDimitry Andric       const uint8_t *P = I + J;
111*06c3fb27SDimitry Andric       if (J % 8 == 0)
112*06c3fb27SDimitry Andric         dbgs() << "  ";
113*06c3fb27SDimitry Andric 
114*06c3fb27SDimitry Andric       dbgs() << format("%02hhX", *P);
115*06c3fb27SDimitry Andric     }
116*06c3fb27SDimitry Andric #endif
117*06c3fb27SDimitry Andric     switch (RecordType) {
118*06c3fb27SDimitry Andric     case GOFF::RT_ESD: {
119*06c3fb27SDimitry Andric       // Save ESD record.
120*06c3fb27SDimitry Andric       uint32_t EsdId;
121*06c3fb27SDimitry Andric       ESDRecord::getEsdId(I, EsdId);
122*06c3fb27SDimitry Andric       EsdPtrs.grow(EsdId);
123*06c3fb27SDimitry Andric       EsdPtrs[EsdId] = I;
124*06c3fb27SDimitry Andric 
125*06c3fb27SDimitry Andric       // Determine and save the "sections" in GOFF.
126*06c3fb27SDimitry Andric       // A section is saved as a tuple of the form
127*06c3fb27SDimitry Andric       // case (1): (ED,child PR)
128*06c3fb27SDimitry Andric       //    - where the PR must have non-zero length.
129*06c3fb27SDimitry Andric       // case (2a) (ED,0)
130*06c3fb27SDimitry Andric       //   - where the ED is of non-zero length.
131*06c3fb27SDimitry Andric       // case (2b) (ED,0)
132*06c3fb27SDimitry Andric       //   - where the ED is zero length but
133*06c3fb27SDimitry Andric       //     contains a label (LD).
134*06c3fb27SDimitry Andric       GOFF::ESDSymbolType SymbolType;
135*06c3fb27SDimitry Andric       ESDRecord::getSymbolType(I, SymbolType);
136*06c3fb27SDimitry Andric       SectionEntryImpl Section;
137*06c3fb27SDimitry Andric       uint32_t Length;
138*06c3fb27SDimitry Andric       ESDRecord::getLength(I, Length);
139*06c3fb27SDimitry Andric       if (SymbolType == GOFF::ESD_ST_ElementDefinition) {
140*06c3fb27SDimitry Andric         // case (2a)
141*06c3fb27SDimitry Andric         if (Length != 0) {
142*06c3fb27SDimitry Andric           Section.d.a = EsdId;
143*06c3fb27SDimitry Andric           SectionList.emplace_back(Section);
144*06c3fb27SDimitry Andric         }
145*06c3fb27SDimitry Andric       } else if (SymbolType == GOFF::ESD_ST_PartReference) {
146*06c3fb27SDimitry Andric         // case (1)
147*06c3fb27SDimitry Andric         if (Length != 0) {
148*06c3fb27SDimitry Andric           uint32_t SymEdId;
149*06c3fb27SDimitry Andric           ESDRecord::getParentEsdId(I, SymEdId);
150*06c3fb27SDimitry Andric           Section.d.a = SymEdId;
151*06c3fb27SDimitry Andric           Section.d.b = EsdId;
152*06c3fb27SDimitry Andric           SectionList.emplace_back(Section);
153*06c3fb27SDimitry Andric         }
154*06c3fb27SDimitry Andric       } else if (SymbolType == GOFF::ESD_ST_LabelDefinition) {
155*06c3fb27SDimitry Andric         // case (2b)
156*06c3fb27SDimitry Andric         uint32_t SymEdId;
157*06c3fb27SDimitry Andric         ESDRecord::getParentEsdId(I, SymEdId);
158*06c3fb27SDimitry Andric         const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
159*06c3fb27SDimitry Andric         uint32_t EdLength;
160*06c3fb27SDimitry Andric         ESDRecord::getLength(SymEdRecord, EdLength);
161*06c3fb27SDimitry Andric         if (!EdLength) { // [ EDID, PRID ]
162*06c3fb27SDimitry Andric           // LD child of a zero length parent ED.
163*06c3fb27SDimitry Andric           // Add the section ED which was previously ignored.
164*06c3fb27SDimitry Andric           Section.d.a = SymEdId;
165*06c3fb27SDimitry Andric           SectionList.emplace_back(Section);
166*06c3fb27SDimitry Andric         }
167*06c3fb27SDimitry Andric       }
168*06c3fb27SDimitry Andric       LLVM_DEBUG(dbgs() << "  --  ESD " << EsdId << "\n");
169*06c3fb27SDimitry Andric       break;
170*06c3fb27SDimitry Andric     }
171*06c3fb27SDimitry Andric     case GOFF::RT_END:
172*06c3fb27SDimitry Andric       LLVM_DEBUG(dbgs() << "  --  END (GOFF record type) unhandled\n");
173*06c3fb27SDimitry Andric       break;
174*06c3fb27SDimitry Andric     case GOFF::RT_HDR:
175*06c3fb27SDimitry Andric       LLVM_DEBUG(dbgs() << "  --  HDR (GOFF record type) unhandled\n");
176*06c3fb27SDimitry Andric       break;
177*06c3fb27SDimitry Andric     default:
178*06c3fb27SDimitry Andric       llvm_unreachable("Unknown record type");
179*06c3fb27SDimitry Andric     }
180*06c3fb27SDimitry Andric     PrevRecordType = RecordType;
181*06c3fb27SDimitry Andric     PrevContinuationBits = I[1] & 0x03;
182*06c3fb27SDimitry Andric   }
183*06c3fb27SDimitry Andric }
184*06c3fb27SDimitry Andric 
185*06c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {
186*06c3fb27SDimitry Andric   const uint8_t *EsdRecord = EsdPtrs[Symb.d.a];
187*06c3fb27SDimitry Andric   return EsdRecord;
188*06c3fb27SDimitry Andric }
189*06c3fb27SDimitry Andric 
190*06c3fb27SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
191*06c3fb27SDimitry Andric   if (EsdNamesCache.count(Symb.d.a)) {
192*06c3fb27SDimitry Andric     auto &StrPtr = EsdNamesCache[Symb.d.a];
193*06c3fb27SDimitry Andric     return StringRef(StrPtr.second.get(), StrPtr.first);
194*06c3fb27SDimitry Andric   }
195*06c3fb27SDimitry Andric 
196*06c3fb27SDimitry Andric   SmallString<256> SymbolName;
197*06c3fb27SDimitry Andric   if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName))
198*06c3fb27SDimitry Andric     return std::move(Err);
199*06c3fb27SDimitry Andric 
200*06c3fb27SDimitry Andric   SmallString<256> SymbolNameConverted;
201*06c3fb27SDimitry Andric   ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted);
202*06c3fb27SDimitry Andric 
203*06c3fb27SDimitry Andric   size_t Size = SymbolNameConverted.size();
204*06c3fb27SDimitry Andric   auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size));
205*06c3fb27SDimitry Andric   char *Buf = StrPtr.second.get();
206*06c3fb27SDimitry Andric   memcpy(Buf, SymbolNameConverted.data(), Size);
207*06c3fb27SDimitry Andric   EsdNamesCache[Symb.d.a] = std::move(StrPtr);
208*06c3fb27SDimitry Andric   return StringRef(Buf, Size);
209*06c3fb27SDimitry Andric }
210*06c3fb27SDimitry Andric 
211*06c3fb27SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const {
212*06c3fb27SDimitry Andric   return getSymbolName(Symbol.getRawDataRefImpl());
213*06c3fb27SDimitry Andric }
214*06c3fb27SDimitry Andric 
215*06c3fb27SDimitry Andric Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
216*06c3fb27SDimitry Andric   uint32_t Offset;
217*06c3fb27SDimitry Andric   const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
218*06c3fb27SDimitry Andric   ESDRecord::getOffset(EsdRecord, Offset);
219*06c3fb27SDimitry Andric   return static_cast<uint64_t>(Offset);
220*06c3fb27SDimitry Andric }
221*06c3fb27SDimitry Andric 
222*06c3fb27SDimitry Andric uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
223*06c3fb27SDimitry Andric   uint32_t Offset;
224*06c3fb27SDimitry Andric   const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
225*06c3fb27SDimitry Andric   ESDRecord::getOffset(EsdRecord, Offset);
226*06c3fb27SDimitry Andric   return static_cast<uint64_t>(Offset);
227*06c3fb27SDimitry Andric }
228*06c3fb27SDimitry Andric 
229*06c3fb27SDimitry Andric uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
230*06c3fb27SDimitry Andric   return 0;
231*06c3fb27SDimitry Andric }
232*06c3fb27SDimitry Andric 
233*06c3fb27SDimitry Andric bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {
234*06c3fb27SDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
235*06c3fb27SDimitry Andric   GOFF::ESDSymbolType SymbolType;
236*06c3fb27SDimitry Andric   ESDRecord::getSymbolType(Record, SymbolType);
237*06c3fb27SDimitry Andric 
238*06c3fb27SDimitry Andric   if (SymbolType == GOFF::ESD_ST_ExternalReference)
239*06c3fb27SDimitry Andric     return true;
240*06c3fb27SDimitry Andric   if (SymbolType == GOFF::ESD_ST_PartReference) {
241*06c3fb27SDimitry Andric     uint32_t Length;
242*06c3fb27SDimitry Andric     ESDRecord::getLength(Record, Length);
243*06c3fb27SDimitry Andric     if (Length == 0)
244*06c3fb27SDimitry Andric       return true;
245*06c3fb27SDimitry Andric   }
246*06c3fb27SDimitry Andric   return false;
247*06c3fb27SDimitry Andric }
248*06c3fb27SDimitry Andric 
249*06c3fb27SDimitry Andric bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {
250*06c3fb27SDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
251*06c3fb27SDimitry Andric   bool Indirect;
252*06c3fb27SDimitry Andric   ESDRecord::getIndirectReference(Record, Indirect);
253*06c3fb27SDimitry Andric   return Indirect;
254*06c3fb27SDimitry Andric }
255*06c3fb27SDimitry Andric 
256*06c3fb27SDimitry Andric Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
257*06c3fb27SDimitry Andric   uint32_t Flags = 0;
258*06c3fb27SDimitry Andric   if (isSymbolUnresolved(Symb))
259*06c3fb27SDimitry Andric     Flags |= SymbolRef::SF_Undefined;
260*06c3fb27SDimitry Andric 
261*06c3fb27SDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
262*06c3fb27SDimitry Andric 
263*06c3fb27SDimitry Andric   GOFF::ESDBindingStrength BindingStrength;
264*06c3fb27SDimitry Andric   ESDRecord::getBindingStrength(Record, BindingStrength);
265*06c3fb27SDimitry Andric   if (BindingStrength == GOFF::ESD_BST_Weak)
266*06c3fb27SDimitry Andric     Flags |= SymbolRef::SF_Weak;
267*06c3fb27SDimitry Andric 
268*06c3fb27SDimitry Andric   GOFF::ESDBindingScope BindingScope;
269*06c3fb27SDimitry Andric   ESDRecord::getBindingScope(Record, BindingScope);
270*06c3fb27SDimitry Andric 
271*06c3fb27SDimitry Andric   if (BindingScope != GOFF::ESD_BSC_Section) {
272*06c3fb27SDimitry Andric     Expected<StringRef> Name = getSymbolName(Symb);
273*06c3fb27SDimitry Andric     if (Name && *Name != " ") { // Blank name is local.
274*06c3fb27SDimitry Andric       Flags |= SymbolRef::SF_Global;
275*06c3fb27SDimitry Andric       if (BindingScope == GOFF::ESD_BSC_ImportExport)
276*06c3fb27SDimitry Andric         Flags |= SymbolRef::SF_Exported;
277*06c3fb27SDimitry Andric       else if (!(Flags & SymbolRef::SF_Undefined))
278*06c3fb27SDimitry Andric         Flags |= SymbolRef::SF_Hidden;
279*06c3fb27SDimitry Andric     }
280*06c3fb27SDimitry Andric   }
281*06c3fb27SDimitry Andric 
282*06c3fb27SDimitry Andric   return Flags;
283*06c3fb27SDimitry Andric }
284*06c3fb27SDimitry Andric 
285*06c3fb27SDimitry Andric Expected<SymbolRef::Type>
286*06c3fb27SDimitry Andric GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
287*06c3fb27SDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
288*06c3fb27SDimitry Andric   GOFF::ESDSymbolType SymbolType;
289*06c3fb27SDimitry Andric   ESDRecord::getSymbolType(Record, SymbolType);
290*06c3fb27SDimitry Andric   GOFF::ESDExecutable Executable;
291*06c3fb27SDimitry Andric   ESDRecord::getExecutable(Record, Executable);
292*06c3fb27SDimitry Andric 
293*06c3fb27SDimitry Andric   if (SymbolType != GOFF::ESD_ST_SectionDefinition &&
294*06c3fb27SDimitry Andric       SymbolType != GOFF::ESD_ST_ElementDefinition &&
295*06c3fb27SDimitry Andric       SymbolType != GOFF::ESD_ST_LabelDefinition &&
296*06c3fb27SDimitry Andric       SymbolType != GOFF::ESD_ST_PartReference &&
297*06c3fb27SDimitry Andric       SymbolType != GOFF::ESD_ST_ExternalReference) {
298*06c3fb27SDimitry Andric     uint32_t EsdId;
299*06c3fb27SDimitry Andric     ESDRecord::getEsdId(Record, EsdId);
300*06c3fb27SDimitry Andric     return createStringError(llvm::errc::invalid_argument,
301*06c3fb27SDimitry Andric                              "ESD record %" PRIu32
302*06c3fb27SDimitry Andric                              " has invalid symbol type 0x%02" PRIX8,
303*06c3fb27SDimitry Andric                              EsdId, SymbolType);
304*06c3fb27SDimitry Andric   }
305*06c3fb27SDimitry Andric   switch (SymbolType) {
306*06c3fb27SDimitry Andric   case GOFF::ESD_ST_SectionDefinition:
307*06c3fb27SDimitry Andric   case GOFF::ESD_ST_ElementDefinition:
308*06c3fb27SDimitry Andric     return SymbolRef::ST_Other;
309*06c3fb27SDimitry Andric   case GOFF::ESD_ST_LabelDefinition:
310*06c3fb27SDimitry Andric   case GOFF::ESD_ST_PartReference:
311*06c3fb27SDimitry Andric   case GOFF::ESD_ST_ExternalReference:
312*06c3fb27SDimitry Andric     if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA &&
313*06c3fb27SDimitry Andric         Executable != GOFF::ESD_EXE_Unspecified) {
314*06c3fb27SDimitry Andric       uint32_t EsdId;
315*06c3fb27SDimitry Andric       ESDRecord::getEsdId(Record, EsdId);
316*06c3fb27SDimitry Andric       return createStringError(llvm::errc::invalid_argument,
317*06c3fb27SDimitry Andric                                "ESD record %" PRIu32
318*06c3fb27SDimitry Andric                                " has unknown Executable type 0x%02X",
319*06c3fb27SDimitry Andric                                EsdId, Executable);
320*06c3fb27SDimitry Andric     }
321*06c3fb27SDimitry Andric     switch (Executable) {
322*06c3fb27SDimitry Andric     case GOFF::ESD_EXE_CODE:
323*06c3fb27SDimitry Andric       return SymbolRef::ST_Function;
324*06c3fb27SDimitry Andric     case GOFF::ESD_EXE_DATA:
325*06c3fb27SDimitry Andric       return SymbolRef::ST_Data;
326*06c3fb27SDimitry Andric     case GOFF::ESD_EXE_Unspecified:
327*06c3fb27SDimitry Andric       return SymbolRef::ST_Unknown;
328*06c3fb27SDimitry Andric     }
329*06c3fb27SDimitry Andric     llvm_unreachable("Unhandled ESDExecutable");
330*06c3fb27SDimitry Andric   }
331*06c3fb27SDimitry Andric   llvm_unreachable("Unhandled ESDSymbolType");
332*06c3fb27SDimitry Andric }
333*06c3fb27SDimitry Andric 
334*06c3fb27SDimitry Andric Expected<section_iterator>
335*06c3fb27SDimitry Andric GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
336*06c3fb27SDimitry Andric   DataRefImpl Sec;
337*06c3fb27SDimitry Andric 
338*06c3fb27SDimitry Andric   if (isSymbolUnresolved(Symb))
339*06c3fb27SDimitry Andric     return section_iterator(SectionRef(Sec, this));
340*06c3fb27SDimitry Andric 
341*06c3fb27SDimitry Andric   const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a];
342*06c3fb27SDimitry Andric   uint32_t SymEdId;
343*06c3fb27SDimitry Andric   ESDRecord::getParentEsdId(SymEsdRecord, SymEdId);
344*06c3fb27SDimitry Andric   const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
345*06c3fb27SDimitry Andric 
346*06c3fb27SDimitry Andric   for (size_t I = 0, E = SectionList.size(); I < E; ++I) {
347*06c3fb27SDimitry Andric     bool Found;
348*06c3fb27SDimitry Andric     const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I);
349*06c3fb27SDimitry Andric     if (SectionPrRecord) {
350*06c3fb27SDimitry Andric       Found = SymEsdRecord == SectionPrRecord;
351*06c3fb27SDimitry Andric     } else {
352*06c3fb27SDimitry Andric       const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I);
353*06c3fb27SDimitry Andric       Found = SymEdRecord == SectionEdRecord;
354*06c3fb27SDimitry Andric     }
355*06c3fb27SDimitry Andric 
356*06c3fb27SDimitry Andric     if (Found) {
357*06c3fb27SDimitry Andric       Sec.d.a = I;
358*06c3fb27SDimitry Andric       return section_iterator(SectionRef(Sec, this));
359*06c3fb27SDimitry Andric     }
360*06c3fb27SDimitry Andric   }
361*06c3fb27SDimitry Andric   return createStringError(llvm::errc::invalid_argument,
362*06c3fb27SDimitry Andric                            "symbol with ESD id " + std::to_string(Symb.d.a) +
363*06c3fb27SDimitry Andric                                " refers to invalid section with ESD id " +
364*06c3fb27SDimitry Andric                                std::to_string(SymEdId));
365*06c3fb27SDimitry Andric }
366*06c3fb27SDimitry Andric 
367*06c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
368*06c3fb27SDimitry Andric   SectionEntryImpl EsdIds = SectionList[Sec.d.a];
369*06c3fb27SDimitry Andric   const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
370*06c3fb27SDimitry Andric   return EsdRecord;
371*06c3fb27SDimitry Andric }
372*06c3fb27SDimitry Andric 
373*06c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const {
374*06c3fb27SDimitry Andric   SectionEntryImpl EsdIds = SectionList[Sec.d.a];
375*06c3fb27SDimitry Andric   const uint8_t *EsdRecord = nullptr;
376*06c3fb27SDimitry Andric   if (EsdIds.d.b)
377*06c3fb27SDimitry Andric     EsdRecord = EsdPtrs[EsdIds.d.b];
378*06c3fb27SDimitry Andric   return EsdRecord;
379*06c3fb27SDimitry Andric }
380*06c3fb27SDimitry Andric 
381*06c3fb27SDimitry Andric const uint8_t *
382*06c3fb27SDimitry Andric GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {
383*06c3fb27SDimitry Andric   DataRefImpl Sec;
384*06c3fb27SDimitry Andric   Sec.d.a = SectionIndex;
385*06c3fb27SDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
386*06c3fb27SDimitry Andric   return EsdRecord;
387*06c3fb27SDimitry Andric }
388*06c3fb27SDimitry Andric 
389*06c3fb27SDimitry Andric const uint8_t *
390*06c3fb27SDimitry Andric GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
391*06c3fb27SDimitry Andric   DataRefImpl Sec;
392*06c3fb27SDimitry Andric   Sec.d.a = SectionIndex;
393*06c3fb27SDimitry Andric   const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
394*06c3fb27SDimitry Andric   return EsdRecord;
395*06c3fb27SDimitry Andric }
396*06c3fb27SDimitry Andric 
397*06c3fb27SDimitry Andric section_iterator GOFFObjectFile::section_begin() const {
398*06c3fb27SDimitry Andric   DataRefImpl Sec;
399*06c3fb27SDimitry Andric   moveSectionNext(Sec);
400*06c3fb27SDimitry Andric   return section_iterator(SectionRef(Sec, this));
401*06c3fb27SDimitry Andric }
402*06c3fb27SDimitry Andric 
403*06c3fb27SDimitry Andric section_iterator GOFFObjectFile::section_end() const {
404*06c3fb27SDimitry Andric   DataRefImpl Sec;
405*06c3fb27SDimitry Andric   return section_iterator(SectionRef(Sec, this));
406*06c3fb27SDimitry Andric }
407*06c3fb27SDimitry Andric 
408*06c3fb27SDimitry Andric void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
409*06c3fb27SDimitry Andric   for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) {
410*06c3fb27SDimitry Andric     if (EsdPtrs[I]) {
411*06c3fb27SDimitry Andric       const uint8_t *EsdRecord = EsdPtrs[I];
412*06c3fb27SDimitry Andric       GOFF::ESDSymbolType SymbolType;
413*06c3fb27SDimitry Andric       ESDRecord::getSymbolType(EsdRecord, SymbolType);
414*06c3fb27SDimitry Andric       // Skip EDs - i.e. section symbols.
415*06c3fb27SDimitry Andric       bool IgnoreSpecialGOFFSymbols = true;
416*06c3fb27SDimitry Andric       bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) ||
417*06c3fb27SDimitry Andric                          (SymbolType == GOFF::ESD_ST_SectionDefinition)) &&
418*06c3fb27SDimitry Andric                         IgnoreSpecialGOFFSymbols;
419*06c3fb27SDimitry Andric       if (!SkipSymbol) {
420*06c3fb27SDimitry Andric         Symb.d.a = I;
421*06c3fb27SDimitry Andric         return;
422*06c3fb27SDimitry Andric       }
423*06c3fb27SDimitry Andric     }
424*06c3fb27SDimitry Andric   }
425*06c3fb27SDimitry Andric   Symb.d.a = 0;
426*06c3fb27SDimitry Andric }
427*06c3fb27SDimitry Andric 
428*06c3fb27SDimitry Andric basic_symbol_iterator GOFFObjectFile::symbol_begin() const {
429*06c3fb27SDimitry Andric   DataRefImpl Symb;
430*06c3fb27SDimitry Andric   moveSymbolNext(Symb);
431*06c3fb27SDimitry Andric   return basic_symbol_iterator(SymbolRef(Symb, this));
432*06c3fb27SDimitry Andric }
433*06c3fb27SDimitry Andric 
434*06c3fb27SDimitry Andric basic_symbol_iterator GOFFObjectFile::symbol_end() const {
435*06c3fb27SDimitry Andric   DataRefImpl Symb;
436*06c3fb27SDimitry Andric   return basic_symbol_iterator(SymbolRef(Symb, this));
437*06c3fb27SDimitry Andric }
438*06c3fb27SDimitry Andric 
439*06c3fb27SDimitry Andric Error Record::getContinuousData(const uint8_t *Record, uint16_t DataLength,
440*06c3fb27SDimitry Andric                                 int DataIndex, SmallString<256> &CompleteData) {
441*06c3fb27SDimitry Andric   // First record.
442*06c3fb27SDimitry Andric   const uint8_t *Slice = Record + DataIndex;
443*06c3fb27SDimitry Andric   size_t SliceLength =
444*06c3fb27SDimitry Andric       std::min(DataLength, (uint16_t)(GOFF::RecordLength - DataIndex));
445*06c3fb27SDimitry Andric   CompleteData.append(Slice, Slice + SliceLength);
446*06c3fb27SDimitry Andric   DataLength -= SliceLength;
447*06c3fb27SDimitry Andric   Slice += SliceLength;
448*06c3fb27SDimitry Andric 
449*06c3fb27SDimitry Andric   // Continuation records.
450*06c3fb27SDimitry Andric   for (; DataLength > 0;
451*06c3fb27SDimitry Andric        DataLength -= SliceLength, Slice += GOFF::PayloadLength) {
452*06c3fb27SDimitry Andric     // Slice points to the start of the new record.
453*06c3fb27SDimitry Andric     // Check that this block is a Continuation.
454*06c3fb27SDimitry Andric     assert(Record::isContinuation(Slice) && "Continuation bit must be set");
455*06c3fb27SDimitry Andric     // Check that the last Continuation is terminated correctly.
456*06c3fb27SDimitry Andric     if (DataLength <= 77 && Record::isContinued(Slice))
457*06c3fb27SDimitry Andric       return createStringError(object_error::parse_failed,
458*06c3fb27SDimitry Andric                                "continued bit should not be set");
459*06c3fb27SDimitry Andric 
460*06c3fb27SDimitry Andric     SliceLength = std::min(DataLength, (uint16_t)GOFF::PayloadLength);
461*06c3fb27SDimitry Andric     Slice += GOFF::RecordPrefixLength;
462*06c3fb27SDimitry Andric     CompleteData.append(Slice, Slice + SliceLength);
463*06c3fb27SDimitry Andric   }
464*06c3fb27SDimitry Andric   return Error::success();
465*06c3fb27SDimitry Andric }
466*06c3fb27SDimitry Andric 
467*06c3fb27SDimitry Andric Error HDRRecord::getData(const uint8_t *Record,
468*06c3fb27SDimitry Andric                          SmallString<256> &CompleteData) {
469*06c3fb27SDimitry Andric   uint16_t Length = getPropertyModuleLength(Record);
470*06c3fb27SDimitry Andric   return getContinuousData(Record, Length, 60, CompleteData);
471*06c3fb27SDimitry Andric }
472*06c3fb27SDimitry Andric 
473*06c3fb27SDimitry Andric Error ESDRecord::getData(const uint8_t *Record,
474*06c3fb27SDimitry Andric                          SmallString<256> &CompleteData) {
475*06c3fb27SDimitry Andric   uint16_t DataSize = getNameLength(Record);
476*06c3fb27SDimitry Andric   return getContinuousData(Record, DataSize, 72, CompleteData);
477*06c3fb27SDimitry Andric }
478*06c3fb27SDimitry Andric 
479*06c3fb27SDimitry Andric Error ENDRecord::getData(const uint8_t *Record,
480*06c3fb27SDimitry Andric                          SmallString<256> &CompleteData) {
481*06c3fb27SDimitry Andric   uint16_t Length = getNameLength(Record);
482*06c3fb27SDimitry Andric   return getContinuousData(Record, Length, 26, CompleteData);
483*06c3fb27SDimitry Andric }
484