Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp
35232 views
1
//===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Implementation of the GOFFObjectFile class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/Object/GOFFObjectFile.h"
14
#include "llvm/BinaryFormat/GOFF.h"
15
#include "llvm/Object/GOFF.h"
16
#include "llvm/Support/Debug.h"
17
#include "llvm/Support/Errc.h"
18
#include "llvm/Support/raw_ostream.h"
19
20
#ifndef DEBUG_TYPE
21
#define DEBUG_TYPE "goff"
22
#endif
23
24
using namespace llvm::object;
25
using namespace llvm;
26
27
Expected<std::unique_ptr<ObjectFile>>
28
ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) {
29
Error Err = Error::success();
30
std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err));
31
if (Err)
32
return std::move(Err);
33
return std::move(Ret);
34
}
35
36
GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
37
: ObjectFile(Binary::ID_GOFF, Object) {
38
ErrorAsOutParameter ErrAsOutParam(&Err);
39
// Object file isn't the right size, bail out early.
40
if ((Object.getBufferSize() % GOFF::RecordLength) != 0) {
41
Err = createStringError(
42
object_error::unexpected_eof,
43
"object file is not the right size. Must be a multiple "
44
"of 80 bytes, but is " +
45
std::to_string(Object.getBufferSize()) + " bytes");
46
return;
47
}
48
// Object file doesn't start/end with HDR/END records.
49
// Bail out early.
50
if (Object.getBufferSize() != 0) {
51
if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) {
52
Err = createStringError(object_error::parse_failed,
53
"object file must start with HDR record");
54
return;
55
}
56
if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 !=
57
GOFF::RT_END) {
58
Err = createStringError(object_error::parse_failed,
59
"object file must end with END record");
60
return;
61
}
62
}
63
64
SectionEntryImpl DummySection;
65
SectionList.emplace_back(DummySection); // Dummy entry at index 0.
66
67
uint8_t PrevRecordType = 0;
68
uint8_t PrevContinuationBits = 0;
69
const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd());
70
for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) {
71
uint8_t RecordType = (I[1] & 0xF0) >> 4;
72
bool IsContinuation = I[1] & 0x02;
73
bool PrevWasContinued = PrevContinuationBits & 0x01;
74
size_t RecordNum = (I - base()) / GOFF::RecordLength;
75
76
// If the previous record was continued, the current record should be a
77
// continuation.
78
if (PrevWasContinued && !IsContinuation) {
79
if (PrevRecordType == RecordType) {
80
Err = createStringError(object_error::parse_failed,
81
"record " + std::to_string(RecordNum) +
82
" is not a continuation record but the "
83
"preceding record is continued");
84
return;
85
}
86
}
87
// Don't parse continuations records, only parse initial record.
88
if (IsContinuation) {
89
if (RecordType != PrevRecordType) {
90
Err = createStringError(object_error::parse_failed,
91
"record " + std::to_string(RecordNum) +
92
" is a continuation record that does not "
93
"match the type of the previous record");
94
return;
95
}
96
if (!PrevWasContinued) {
97
Err = createStringError(object_error::parse_failed,
98
"record " + std::to_string(RecordNum) +
99
" is a continuation record that is not "
100
"preceded by a continued record");
101
return;
102
}
103
PrevRecordType = RecordType;
104
PrevContinuationBits = I[1] & 0x03;
105
continue;
106
}
107
LLVM_DEBUG(for (size_t J = 0; J < GOFF::RecordLength; ++J) {
108
const uint8_t *P = I + J;
109
if (J % 8 == 0)
110
dbgs() << " ";
111
dbgs() << format("%02hhX", *P);
112
});
113
114
switch (RecordType) {
115
case GOFF::RT_ESD: {
116
// Save ESD record.
117
uint32_t EsdId;
118
ESDRecord::getEsdId(I, EsdId);
119
EsdPtrs.grow(EsdId);
120
EsdPtrs[EsdId] = I;
121
122
// Determine and save the "sections" in GOFF.
123
// A section is saved as a tuple of the form
124
// case (1): (ED,child PR)
125
// - where the PR must have non-zero length.
126
// case (2a) (ED,0)
127
// - where the ED is of non-zero length.
128
// case (2b) (ED,0)
129
// - where the ED is zero length but
130
// contains a label (LD).
131
GOFF::ESDSymbolType SymbolType;
132
ESDRecord::getSymbolType(I, SymbolType);
133
SectionEntryImpl Section;
134
uint32_t Length;
135
ESDRecord::getLength(I, Length);
136
if (SymbolType == GOFF::ESD_ST_ElementDefinition) {
137
// case (2a)
138
if (Length != 0) {
139
Section.d.a = EsdId;
140
SectionList.emplace_back(Section);
141
}
142
} else if (SymbolType == GOFF::ESD_ST_PartReference) {
143
// case (1)
144
if (Length != 0) {
145
uint32_t SymEdId;
146
ESDRecord::getParentEsdId(I, SymEdId);
147
Section.d.a = SymEdId;
148
Section.d.b = EsdId;
149
SectionList.emplace_back(Section);
150
}
151
} else if (SymbolType == GOFF::ESD_ST_LabelDefinition) {
152
// case (2b)
153
uint32_t SymEdId;
154
ESDRecord::getParentEsdId(I, SymEdId);
155
const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
156
uint32_t EdLength;
157
ESDRecord::getLength(SymEdRecord, EdLength);
158
if (!EdLength) { // [ EDID, PRID ]
159
// LD child of a zero length parent ED.
160
// Add the section ED which was previously ignored.
161
Section.d.a = SymEdId;
162
SectionList.emplace_back(Section);
163
}
164
}
165
LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n");
166
break;
167
}
168
case GOFF::RT_TXT:
169
// Save TXT records.
170
TextPtrs.emplace_back(I);
171
LLVM_DEBUG(dbgs() << " -- TXT\n");
172
break;
173
case GOFF::RT_END:
174
LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n");
175
break;
176
case GOFF::RT_HDR:
177
LLVM_DEBUG(dbgs() << " -- HDR (GOFF record type) unhandled\n");
178
break;
179
default:
180
llvm_unreachable("Unknown record type");
181
}
182
PrevRecordType = RecordType;
183
PrevContinuationBits = I[1] & 0x03;
184
}
185
}
186
187
const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {
188
const uint8_t *EsdRecord = EsdPtrs[Symb.d.a];
189
return EsdRecord;
190
}
191
192
Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
193
if (EsdNamesCache.count(Symb.d.a)) {
194
auto &StrPtr = EsdNamesCache[Symb.d.a];
195
return StringRef(StrPtr.second.get(), StrPtr.first);
196
}
197
198
SmallString<256> SymbolName;
199
if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName))
200
return std::move(Err);
201
202
SmallString<256> SymbolNameConverted;
203
ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted);
204
205
size_t Size = SymbolNameConverted.size();
206
auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size));
207
char *Buf = StrPtr.second.get();
208
memcpy(Buf, SymbolNameConverted.data(), Size);
209
EsdNamesCache[Symb.d.a] = std::move(StrPtr);
210
return StringRef(Buf, Size);
211
}
212
213
Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const {
214
return getSymbolName(Symbol.getRawDataRefImpl());
215
}
216
217
Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
218
uint32_t Offset;
219
const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
220
ESDRecord::getOffset(EsdRecord, Offset);
221
return static_cast<uint64_t>(Offset);
222
}
223
224
uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
225
uint32_t Offset;
226
const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
227
ESDRecord::getOffset(EsdRecord, Offset);
228
return static_cast<uint64_t>(Offset);
229
}
230
231
uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
232
return 0;
233
}
234
235
bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {
236
const uint8_t *Record = getSymbolEsdRecord(Symb);
237
GOFF::ESDSymbolType SymbolType;
238
ESDRecord::getSymbolType(Record, SymbolType);
239
240
if (SymbolType == GOFF::ESD_ST_ExternalReference)
241
return true;
242
if (SymbolType == GOFF::ESD_ST_PartReference) {
243
uint32_t Length;
244
ESDRecord::getLength(Record, Length);
245
if (Length == 0)
246
return true;
247
}
248
return false;
249
}
250
251
bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {
252
const uint8_t *Record = getSymbolEsdRecord(Symb);
253
bool Indirect;
254
ESDRecord::getIndirectReference(Record, Indirect);
255
return Indirect;
256
}
257
258
Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
259
uint32_t Flags = 0;
260
if (isSymbolUnresolved(Symb))
261
Flags |= SymbolRef::SF_Undefined;
262
263
const uint8_t *Record = getSymbolEsdRecord(Symb);
264
265
GOFF::ESDBindingStrength BindingStrength;
266
ESDRecord::getBindingStrength(Record, BindingStrength);
267
if (BindingStrength == GOFF::ESD_BST_Weak)
268
Flags |= SymbolRef::SF_Weak;
269
270
GOFF::ESDBindingScope BindingScope;
271
ESDRecord::getBindingScope(Record, BindingScope);
272
273
if (BindingScope != GOFF::ESD_BSC_Section) {
274
Expected<StringRef> Name = getSymbolName(Symb);
275
if (Name && *Name != " ") { // Blank name is local.
276
Flags |= SymbolRef::SF_Global;
277
if (BindingScope == GOFF::ESD_BSC_ImportExport)
278
Flags |= SymbolRef::SF_Exported;
279
else if (!(Flags & SymbolRef::SF_Undefined))
280
Flags |= SymbolRef::SF_Hidden;
281
}
282
}
283
284
return Flags;
285
}
286
287
Expected<SymbolRef::Type>
288
GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
289
const uint8_t *Record = getSymbolEsdRecord(Symb);
290
GOFF::ESDSymbolType SymbolType;
291
ESDRecord::getSymbolType(Record, SymbolType);
292
GOFF::ESDExecutable Executable;
293
ESDRecord::getExecutable(Record, Executable);
294
295
if (SymbolType != GOFF::ESD_ST_SectionDefinition &&
296
SymbolType != GOFF::ESD_ST_ElementDefinition &&
297
SymbolType != GOFF::ESD_ST_LabelDefinition &&
298
SymbolType != GOFF::ESD_ST_PartReference &&
299
SymbolType != GOFF::ESD_ST_ExternalReference) {
300
uint32_t EsdId;
301
ESDRecord::getEsdId(Record, EsdId);
302
return createStringError(llvm::errc::invalid_argument,
303
"ESD record %" PRIu32
304
" has invalid symbol type 0x%02" PRIX8,
305
EsdId, SymbolType);
306
}
307
switch (SymbolType) {
308
case GOFF::ESD_ST_SectionDefinition:
309
case GOFF::ESD_ST_ElementDefinition:
310
return SymbolRef::ST_Other;
311
case GOFF::ESD_ST_LabelDefinition:
312
case GOFF::ESD_ST_PartReference:
313
case GOFF::ESD_ST_ExternalReference:
314
if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA &&
315
Executable != GOFF::ESD_EXE_Unspecified) {
316
uint32_t EsdId;
317
ESDRecord::getEsdId(Record, EsdId);
318
return createStringError(llvm::errc::invalid_argument,
319
"ESD record %" PRIu32
320
" has unknown Executable type 0x%02X",
321
EsdId, Executable);
322
}
323
switch (Executable) {
324
case GOFF::ESD_EXE_CODE:
325
return SymbolRef::ST_Function;
326
case GOFF::ESD_EXE_DATA:
327
return SymbolRef::ST_Data;
328
case GOFF::ESD_EXE_Unspecified:
329
return SymbolRef::ST_Unknown;
330
}
331
llvm_unreachable("Unhandled ESDExecutable");
332
}
333
llvm_unreachable("Unhandled ESDSymbolType");
334
}
335
336
Expected<section_iterator>
337
GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
338
DataRefImpl Sec;
339
340
if (isSymbolUnresolved(Symb))
341
return section_iterator(SectionRef(Sec, this));
342
343
const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a];
344
uint32_t SymEdId;
345
ESDRecord::getParentEsdId(SymEsdRecord, SymEdId);
346
const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
347
348
for (size_t I = 0, E = SectionList.size(); I < E; ++I) {
349
bool Found;
350
const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I);
351
if (SectionPrRecord) {
352
Found = SymEsdRecord == SectionPrRecord;
353
} else {
354
const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I);
355
Found = SymEdRecord == SectionEdRecord;
356
}
357
358
if (Found) {
359
Sec.d.a = I;
360
return section_iterator(SectionRef(Sec, this));
361
}
362
}
363
return createStringError(llvm::errc::invalid_argument,
364
"symbol with ESD id " + std::to_string(Symb.d.a) +
365
" refers to invalid section with ESD id " +
366
std::to_string(SymEdId));
367
}
368
369
uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
370
const uint8_t *Record = getSymbolEsdRecord(Symb);
371
uint32_t Length;
372
ESDRecord::getLength(Record, Length);
373
return Length;
374
}
375
376
const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
377
SectionEntryImpl EsdIds = SectionList[Sec.d.a];
378
const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
379
return EsdRecord;
380
}
381
382
const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const {
383
SectionEntryImpl EsdIds = SectionList[Sec.d.a];
384
const uint8_t *EsdRecord = nullptr;
385
if (EsdIds.d.b)
386
EsdRecord = EsdPtrs[EsdIds.d.b];
387
return EsdRecord;
388
}
389
390
const uint8_t *
391
GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {
392
DataRefImpl Sec;
393
Sec.d.a = SectionIndex;
394
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
395
return EsdRecord;
396
}
397
398
const uint8_t *
399
GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
400
DataRefImpl Sec;
401
Sec.d.a = SectionIndex;
402
const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
403
return EsdRecord;
404
}
405
406
uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const {
407
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
408
uint32_t Length;
409
ESDRecord::getLength(EsdRecord, Length);
410
if (Length == 0) {
411
const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
412
if (PrEsdRecord)
413
EsdRecord = PrEsdRecord;
414
}
415
416
uint32_t DefEsdId;
417
ESDRecord::getEsdId(EsdRecord, DefEsdId);
418
LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n');
419
return DefEsdId;
420
}
421
422
void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
423
Sec.d.a++;
424
if ((Sec.d.a) >= SectionList.size())
425
Sec.d.a = 0;
426
}
427
428
Expected<StringRef> GOFFObjectFile::getSectionName(DataRefImpl Sec) const {
429
DataRefImpl EdSym;
430
SectionEntryImpl EsdIds = SectionList[Sec.d.a];
431
EdSym.d.a = EsdIds.d.a;
432
Expected<StringRef> Name = getSymbolName(EdSym);
433
if (Name) {
434
StringRef Res = *Name;
435
LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n');
436
LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n');
437
Name = Res;
438
}
439
return Name;
440
}
441
442
uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
443
uint32_t Offset;
444
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
445
ESDRecord::getOffset(EsdRecord, Offset);
446
return Offset;
447
}
448
449
uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
450
uint32_t Length;
451
uint32_t DefEsdId = getSectionDefEsdId(Sec);
452
const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
453
ESDRecord::getLength(EsdRecord, Length);
454
LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n');
455
return static_cast<uint64_t>(Length);
456
}
457
458
// Unravel TXT records and expand fill characters to produce
459
// a contiguous sequence of bytes.
460
Expected<ArrayRef<uint8_t>>
461
GOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
462
if (SectionDataCache.count(Sec.d.a)) {
463
auto &Buf = SectionDataCache[Sec.d.a];
464
return ArrayRef<uint8_t>(Buf);
465
}
466
uint64_t SectionSize = getSectionSize(Sec);
467
uint32_t DefEsdId = getSectionDefEsdId(Sec);
468
469
const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
470
bool FillBytePresent;
471
ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent);
472
uint8_t FillByte = '\0';
473
if (FillBytePresent)
474
ESDRecord::getFillByteValue(EdEsdRecord, FillByte);
475
476
// Initialize section with fill byte.
477
SmallVector<uint8_t> Data(SectionSize, FillByte);
478
479
// Replace section with content from text records.
480
for (const uint8_t *TxtRecordInt : TextPtrs) {
481
const uint8_t *TxtRecordPtr = TxtRecordInt;
482
uint32_t TxtEsdId;
483
TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId);
484
LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n');
485
486
if (TxtEsdId != DefEsdId)
487
continue;
488
489
uint32_t TxtDataOffset;
490
TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset);
491
492
uint16_t TxtDataSize;
493
TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize);
494
495
LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size "
496
<< TxtDataSize << "\n");
497
498
SmallString<256> CompleteData;
499
CompleteData.reserve(TxtDataSize);
500
if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData))
501
return std::move(Err);
502
assert(CompleteData.size() == TxtDataSize && "Wrong length of data");
503
std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize,
504
Data.begin() + TxtDataOffset);
505
}
506
SectionDataCache[Sec.d.a] = Data;
507
return ArrayRef<uint8_t>(SectionDataCache[Sec.d.a]);
508
}
509
510
uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
511
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
512
GOFF::ESDAlignment Pow2Alignment;
513
ESDRecord::getAlignment(EsdRecord, Pow2Alignment);
514
return 1ULL << static_cast<uint64_t>(Pow2Alignment);
515
}
516
517
bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const {
518
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
519
GOFF::ESDExecutable Executable;
520
ESDRecord::getExecutable(EsdRecord, Executable);
521
return Executable == GOFF::ESD_EXE_CODE;
522
}
523
524
bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const {
525
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
526
GOFF::ESDExecutable Executable;
527
ESDRecord::getExecutable(EsdRecord, Executable);
528
return Executable == GOFF::ESD_EXE_DATA;
529
}
530
531
bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const {
532
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
533
GOFF::ESDLoadingBehavior LoadingBehavior;
534
ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
535
return LoadingBehavior == GOFF::ESD_LB_NoLoad;
536
}
537
538
bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
539
if (!isSectionData(Sec))
540
return false;
541
542
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
543
GOFF::ESDLoadingBehavior LoadingBehavior;
544
ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
545
return LoadingBehavior == GOFF::ESD_LB_Initial;
546
}
547
548
bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
549
// GOFF uses fill characters and fill characters are applied
550
// on getSectionContents() - so we say false to zero init.
551
return false;
552
}
553
554
section_iterator GOFFObjectFile::section_begin() const {
555
DataRefImpl Sec;
556
moveSectionNext(Sec);
557
return section_iterator(SectionRef(Sec, this));
558
}
559
560
section_iterator GOFFObjectFile::section_end() const {
561
DataRefImpl Sec;
562
return section_iterator(SectionRef(Sec, this));
563
}
564
565
void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
566
for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) {
567
if (EsdPtrs[I]) {
568
const uint8_t *EsdRecord = EsdPtrs[I];
569
GOFF::ESDSymbolType SymbolType;
570
ESDRecord::getSymbolType(EsdRecord, SymbolType);
571
// Skip EDs - i.e. section symbols.
572
bool IgnoreSpecialGOFFSymbols = true;
573
bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) ||
574
(SymbolType == GOFF::ESD_ST_SectionDefinition)) &&
575
IgnoreSpecialGOFFSymbols;
576
if (!SkipSymbol) {
577
Symb.d.a = I;
578
return;
579
}
580
}
581
}
582
Symb.d.a = 0;
583
}
584
585
basic_symbol_iterator GOFFObjectFile::symbol_begin() const {
586
DataRefImpl Symb;
587
moveSymbolNext(Symb);
588
return basic_symbol_iterator(SymbolRef(Symb, this));
589
}
590
591
basic_symbol_iterator GOFFObjectFile::symbol_end() const {
592
DataRefImpl Symb;
593
return basic_symbol_iterator(SymbolRef(Symb, this));
594
}
595
596
Error Record::getContinuousData(const uint8_t *Record, uint16_t DataLength,
597
int DataIndex, SmallString<256> &CompleteData) {
598
// First record.
599
const uint8_t *Slice = Record + DataIndex;
600
size_t SliceLength =
601
std::min(DataLength, (uint16_t)(GOFF::RecordLength - DataIndex));
602
CompleteData.append(Slice, Slice + SliceLength);
603
DataLength -= SliceLength;
604
Slice += SliceLength;
605
606
// Continuation records.
607
for (; DataLength > 0;
608
DataLength -= SliceLength, Slice += GOFF::PayloadLength) {
609
// Slice points to the start of the new record.
610
// Check that this block is a Continuation.
611
assert(Record::isContinuation(Slice) && "Continuation bit must be set");
612
// Check that the last Continuation is terminated correctly.
613
if (DataLength <= 77 && Record::isContinued(Slice))
614
return createStringError(object_error::parse_failed,
615
"continued bit should not be set");
616
617
SliceLength = std::min(DataLength, (uint16_t)GOFF::PayloadLength);
618
Slice += GOFF::RecordPrefixLength;
619
CompleteData.append(Slice, Slice + SliceLength);
620
}
621
return Error::success();
622
}
623
624
Error HDRRecord::getData(const uint8_t *Record,
625
SmallString<256> &CompleteData) {
626
uint16_t Length = getPropertyModuleLength(Record);
627
return getContinuousData(Record, Length, 60, CompleteData);
628
}
629
630
Error ESDRecord::getData(const uint8_t *Record,
631
SmallString<256> &CompleteData) {
632
uint16_t DataSize = getNameLength(Record);
633
return getContinuousData(Record, DataSize, 72, CompleteData);
634
}
635
636
Error TXTRecord::getData(const uint8_t *Record,
637
SmallString<256> &CompleteData) {
638
uint16_t Length;
639
getDataLength(Record, Length);
640
return getContinuousData(Record, Length, 24, CompleteData);
641
}
642
643
Error ENDRecord::getData(const uint8_t *Record,
644
SmallString<256> &CompleteData) {
645
uint16_t Length = getNameLength(Record);
646
return getContinuousData(Record, Length, 26, CompleteData);
647
}
648
649