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