xref: /llvm-project/llvm/unittests/Object/GOFFObjectFileTest.cpp (revision 9d7b35d4e1e0c563e660450687ce475ee1959951)
1 //===- GOFFObjectFileTest.cpp - Tests for GOFFObjectFile ------------------===//
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 #include "llvm/Object/GOFFObjectFile.h"
10 #include "llvm/Support/MemoryBuffer.h"
11 #include "llvm/Testing/Support/Error.h"
12 #include "gtest/gtest.h"
13 
14 using namespace llvm;
15 using namespace llvm::object;
16 using namespace llvm::GOFF;
17 
18 namespace {
19 char GOFFData[GOFF::RecordLength * 3] = {0x00};
20 
21 void constructValidGOFF(size_t Size) {
22   StringRef ValidSize(GOFFData, Size);
23   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
24       object::ObjectFile::createGOFFObjectFile(
25           MemoryBufferRef(ValidSize, "dummyGOFF"));
26 
27   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
28 }
29 
30 void constructInvalidGOFF(size_t Size) {
31   // Construct GOFFObject with record of length != multiple of 80.
32   StringRef InvalidData(GOFFData, Size);
33   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
34       object::ObjectFile::createGOFFObjectFile(
35           MemoryBufferRef(InvalidData, "dummyGOFF"));
36 
37   ASSERT_THAT_EXPECTED(
38       GOFFObjOrErr,
39       FailedWithMessage("object file is not the right size. Must be a multiple "
40                         "of 80 bytes, but is " +
41                         std::to_string(Size) + " bytes"));
42 }
43 } // namespace
44 
45 TEST(GOFFObjectFileTest, ConstructGOFFObjectValidSize) {
46   GOFFData[0] = (char)0x03;
47   GOFFData[1] = (char)0xF0;
48   GOFFData[80] = (char)0x03;
49   GOFFData[81] = (char)0x40;
50   constructValidGOFF(160);
51   constructValidGOFF(0);
52 }
53 
54 TEST(GOFFObjectFileTest, ConstructGOFFObjectInvalidSize) {
55   constructInvalidGOFF(70);
56   constructInvalidGOFF(79);
57   constructInvalidGOFF(81);
58 }
59 
60 TEST(GOFFObjectFileTest, MissingHDR) {
61   char GOFFData[GOFF::RecordLength * 2] = {0x00};
62 
63   // ESD record.
64   GOFFData[0] = (char)0x03;
65 
66   // END record.
67   GOFFData[GOFF::RecordLength] = (char)0x03;
68   GOFFData[GOFF::RecordLength + 1] = (char)0x40;
69 
70   StringRef Data(GOFFData, GOFF::RecordLength * 2);
71 
72   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
73       object::ObjectFile::createGOFFObjectFile(
74           MemoryBufferRef(Data, "dummyGOFF"));
75 
76   ASSERT_THAT_EXPECTED(
77       GOFFObjOrErr,
78       FailedWithMessage("object file must start with HDR record"));
79 }
80 
81 TEST(GOFFObjectFileTest, MissingEND) {
82   char GOFFData[GOFF::RecordLength * 2] = {0x00};
83 
84   // HDR record.
85   GOFFData[0] = (char)0x03;
86   GOFFData[1] = (char)0xF0;
87 
88   // ESD record.
89   GOFFData[GOFF::RecordLength] = (char)0x03;
90 
91   StringRef Data(GOFFData, GOFF::RecordLength * 2);
92 
93   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
94       object::ObjectFile::createGOFFObjectFile(
95           MemoryBufferRef(Data, "dummyGOFF"));
96 
97   ASSERT_THAT_EXPECTED(
98       GOFFObjOrErr, FailedWithMessage("object file must end with END record"));
99 }
100 
101 TEST(GOFFObjectFileTest, GetSymbolName) {
102   char GOFFData[GOFF::RecordLength * 3] = {0x00};
103 
104   // HDR record.
105   GOFFData[0] = (char)0x03;
106   GOFFData[1] = (char)0xF0;
107 
108   // ESD record.
109   GOFFData[GOFF::RecordLength] = (char)0x03;
110   GOFFData[GOFF::RecordLength + 3] = (char)0x02;
111   GOFFData[GOFF::RecordLength + 7] = (char)0x01;
112   GOFFData[GOFF::RecordLength + 11] = (char)0x01;
113   GOFFData[GOFF::RecordLength + 71] = (char)0x05; // Size of symbol name.
114   GOFFData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name is Hello.
115   GOFFData[GOFF::RecordLength + 73] = (char)0x85;
116   GOFFData[GOFF::RecordLength + 74] = (char)0x93;
117   GOFFData[GOFF::RecordLength + 75] = (char)0x93;
118   GOFFData[GOFF::RecordLength + 76] = (char)0x96;
119 
120   // END record.
121   GOFFData[GOFF::RecordLength * 2] = 0x03;
122   GOFFData[GOFF::RecordLength * 2 + 1] = 0x40;
123 
124   StringRef Data(GOFFData, GOFF::RecordLength * 3);
125 
126   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
127       object::ObjectFile::createGOFFObjectFile(
128           MemoryBufferRef(Data, "dummyGOFF"));
129 
130   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
131 
132   GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
133 
134   for (SymbolRef Symbol : GOFFObj->symbols()) {
135     Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
136     ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
137     StringRef SymbolName = SymbolNameOrErr.get();
138 
139     EXPECT_EQ(SymbolName, "Hello");
140   }
141 }
142 
143 TEST(GOFFObjectFileTest, ConcatenatedGOFFFile) {
144   char GOFFData[GOFF::RecordLength * 6] = {0x00};
145 
146   // HDR record.
147   GOFFData[0] = (char)0x03;
148   GOFFData[1] = (char)0xF0;
149   // ESD record.
150   GOFFData[GOFF::RecordLength] = (char)0x03;
151   // END record.
152   GOFFData[GOFF::RecordLength * 2] = (char)0x03;
153   GOFFData[GOFF::RecordLength * 2 + 1] = (char)0x40;
154   // HDR record.
155   GOFFData[GOFF::RecordLength * 3] = (char)0x03;
156   GOFFData[GOFF::RecordLength * 3 + 1] = (char)0xF0;
157   // ESD record.
158   GOFFData[GOFF::RecordLength * 4] = (char)0x03;
159   // END record.
160   GOFFData[GOFF::RecordLength * 5] = (char)0x03;
161   GOFFData[GOFF::RecordLength * 5 + 1] = (char)0x40;
162 
163   StringRef Data(GOFFData, GOFF::RecordLength * 6);
164 
165   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
166       object::ObjectFile::createGOFFObjectFile(
167           MemoryBufferRef(Data, "dummyGOFF"));
168 
169   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
170 }
171 
172 TEST(GOFFObjectFileTest, ContinuationGetSymbolName) {
173   char GOFFContData[GOFF::RecordLength * 4] = {0x00};
174 
175   // HDR record.
176   GOFFContData[0] = (char)0x03;
177   GOFFContData[1] = (char)0xF0;
178 
179   // ESD record.
180   GOFFContData[GOFF::RecordLength] = (char)0x03;
181   GOFFContData[GOFF::RecordLength + 1] = (char)0x01;
182   GOFFContData[GOFF::RecordLength + 3] = (char)0x02;
183   GOFFContData[GOFF::RecordLength + 7] = (char)0x01;
184   GOFFContData[GOFF::RecordLength + 11] = (char)0x01;
185   GOFFContData[GOFF::RecordLength + 71] = (char)0x0A; // Size of symbol name.
186   GOFFContData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name is HelloWorld.
187   GOFFContData[GOFF::RecordLength + 73] = (char)0x85;
188   GOFFContData[GOFF::RecordLength + 74] = (char)0x93;
189   GOFFContData[GOFF::RecordLength + 75] = (char)0x93;
190   GOFFContData[GOFF::RecordLength + 76] = (char)0x96;
191   GOFFContData[GOFF::RecordLength + 77] = (char)0xA6;
192   GOFFContData[GOFF::RecordLength + 78] = (char)0x96;
193   GOFFContData[GOFF::RecordLength + 79] = (char)0x99;
194 
195   // ESD continuation record.
196   GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
197   GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x02; // No further continuations.
198   GOFFContData[GOFF::RecordLength * 2 + 3] = (char)0x93;
199   GOFFContData[GOFF::RecordLength * 2 + 4] = (char)0x84;
200 
201   // END record.
202   GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
203   GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
204 
205   StringRef Data(GOFFContData, GOFF::RecordLength * 4);
206 
207   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
208       object::ObjectFile::createGOFFObjectFile(
209           MemoryBufferRef(Data, "dummyGOFF"));
210 
211   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
212 
213   GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
214 
215   for (SymbolRef Symbol : GOFFObj->symbols()) {
216     Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
217     ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
218     StringRef SymbolName = SymbolNameOrErr.get();
219     EXPECT_EQ(SymbolName, "Helloworld");
220   }
221 }
222 
223 TEST(GOFFObjectFileTest, ContinuationBitNotSet) {
224   char GOFFContData[GOFF::RecordLength * 4] = {0x00};
225 
226   // HDR record.
227   GOFFContData[0] = (char)0x03;
228   GOFFContData[1] = (char)0xF0;
229 
230   // ESD record.
231   GOFFContData[GOFF::RecordLength] = (char)0x03;
232   GOFFContData[GOFF::RecordLength + 1] = (char)0x01;
233   GOFFContData[GOFF::RecordLength + 3] = (char)0x02;
234   GOFFContData[GOFF::RecordLength + 7] = (char)0x01;
235   GOFFContData[GOFF::RecordLength + 11] = (char)0x01;
236   GOFFContData[GOFF::RecordLength + 71] = (char)0x0A; // Size of symbol name.
237   GOFFContData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name is HelloWorld.
238   GOFFContData[GOFF::RecordLength + 73] = (char)0x85;
239   GOFFContData[GOFF::RecordLength + 74] = (char)0x93;
240   GOFFContData[GOFF::RecordLength + 75] = (char)0x93;
241   GOFFContData[GOFF::RecordLength + 76] = (char)0x96;
242   GOFFContData[GOFF::RecordLength + 77] = (char)0xA6;
243   GOFFContData[GOFF::RecordLength + 78] = (char)0x96;
244   GOFFContData[GOFF::RecordLength + 79] = (char)0x99;
245 
246   // ESD continuation record.
247   GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
248   GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x00;
249   GOFFContData[GOFF::RecordLength * 2 + 3] = (char)0x93;
250   GOFFContData[GOFF::RecordLength * 2 + 4] = (char)0x84;
251 
252   // END record.
253   GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
254   GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
255 
256   StringRef Data(GOFFContData, GOFF::RecordLength * 4);
257 
258   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
259       object::ObjectFile::createGOFFObjectFile(
260           MemoryBufferRef(Data, "dummyGOFF"));
261   EXPECT_THAT_EXPECTED(
262       GOFFObjOrErr,
263       FailedWithMessage("record 2 is not a continuation record but the "
264                         "preceding record is continued"));
265 }
266 
267 TEST(GOFFObjectFileTest, ContinuationRecordNotTerminated) {
268   char GOFFContData[GOFF::RecordLength * 4] = {0x00};
269 
270   // HDR record.
271   GOFFContData[0] = (char)0x03;
272   GOFFContData[1] = (char)0xF0;
273 
274   // ESD record.
275   GOFFContData[GOFF::RecordLength] = (char)0x03;
276   GOFFContData[GOFF::RecordLength + 1] = (char)0x01;
277   GOFFContData[GOFF::RecordLength + 3] = (char)0x02;
278   GOFFContData[GOFF::RecordLength + 7] = (char)0x01;
279   GOFFContData[GOFF::RecordLength + 11] = (char)0x01;
280   GOFFContData[GOFF::RecordLength + 71] = (char)0x0A; // Size of symbol name.
281   GOFFContData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name is HelloWorld.
282   GOFFContData[GOFF::RecordLength + 73] = (char)0x85;
283   GOFFContData[GOFF::RecordLength + 74] = (char)0x93;
284   GOFFContData[GOFF::RecordLength + 75] = (char)0x93;
285   GOFFContData[GOFF::RecordLength + 76] = (char)0x96;
286   GOFFContData[GOFF::RecordLength + 77] = (char)0xA6;
287   GOFFContData[GOFF::RecordLength + 78] = (char)0x96;
288   GOFFContData[GOFF::RecordLength + 79] = (char)0x99;
289 
290   // ESD continuation record.
291   GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
292   GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x03; // Continued bit set.
293   GOFFContData[GOFF::RecordLength * 2 + 3] = (char)0x93;
294   GOFFContData[GOFF::RecordLength * 2 + 4] = (char)0x84;
295 
296   // END record.
297   GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
298   GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
299 
300   StringRef Data(GOFFContData, GOFF::RecordLength * 4);
301 
302   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
303       object::ObjectFile::createGOFFObjectFile(
304           MemoryBufferRef(Data, "dummyGOFF"));
305   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
306 
307   GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
308 
309   for (SymbolRef Symbol : GOFFObj->symbols()) {
310     Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
311     EXPECT_THAT_EXPECTED(SymbolNameOrErr,
312                          FailedWithMessage("continued bit should not be set"));
313   }
314 }
315 
316 TEST(GOFFObjectFileTest, PrevNotContinued) {
317   char GOFFContData[GOFF::RecordLength * 4] = {0x00};
318 
319   // HDR record.
320   GOFFContData[0] = (char)0x03;
321   GOFFContData[1] = (char)0xF0;
322 
323   // ESD record, with continued bit not set.
324   GOFFContData[GOFF::RecordLength] = (char)0x03;
325 
326   // ESD continuation record.
327   GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
328   GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x02;
329 
330   // END record.
331   GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
332   GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
333 
334   StringRef Data(GOFFContData, GOFF::RecordLength * 4);
335 
336   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
337       object::ObjectFile::createGOFFObjectFile(
338           MemoryBufferRef(Data, "dummyGOFF"));
339 
340   ASSERT_THAT_EXPECTED(
341       GOFFObjOrErr,
342       FailedWithMessage("record 2 is a continuation record that is not "
343                         "preceded by a continued record"));
344 }
345 
346 TEST(GOFFObjectFileTest, ContinuationTypeMismatch) {
347   char GOFFContData[GOFF::RecordLength * 4] = {0x00};
348 
349   // HDR record.
350   GOFFContData[0] = (char)0x03;
351   GOFFContData[1] = (char)0xF0;
352 
353   // ESD record.
354   GOFFContData[GOFF::RecordLength] = (char)0x03;
355   GOFFContData[GOFF::RecordLength + 1] = (char)0x01; // Continued to next record.
356 
357   // END continuation record.
358   GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
359   GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x42;
360 
361   // END record.
362   GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
363   GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
364 
365   StringRef Data(GOFFContData, GOFF::RecordLength * 4);
366 
367   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
368       object::ObjectFile::createGOFFObjectFile(
369           MemoryBufferRef(Data, "dummyGOFF"));
370 
371   ASSERT_THAT_EXPECTED(
372       GOFFObjOrErr,
373       FailedWithMessage("record 2 is a continuation record that does not match "
374                         "the type of the previous record"));
375 }
376 
377 TEST(GOFFObjectFileTest, TwoSymbols) {
378   char GOFFData[GOFF::RecordLength * 4] = {0x00};
379 
380   // HDR record.
381   GOFFData[0] = (char)0x03;
382   GOFFData[1] = (char)0xF0;
383 
384   // ESD record 1.
385   GOFFData[GOFF::RecordLength] = (char)0x03;
386   GOFFData[GOFF::RecordLength + 3] = (char)0x00;
387   GOFFData[GOFF::RecordLength + 7] = (char)0x01;  // ESDID.
388   GOFFData[GOFF::RecordLength + 71] = (char)0x01; // Size of symbol name.
389   GOFFData[GOFF::RecordLength + 72] = (char)0xa7; // Symbol name is x.
390 
391   // ESD record 2.
392   GOFFData[GOFF::RecordLength * 2] = (char)0x03;
393   GOFFData[GOFF::RecordLength * 2 + 3] = (char)0x03;
394   GOFFData[GOFF::RecordLength * 2 + 7] = (char)0x02;  // ESDID.
395   GOFFData[GOFF::RecordLength * 2 + 11] = (char)0x01; // Parent ESDID.
396   GOFFData[GOFF::RecordLength * 2 + 71] = (char)0x05; // Size of symbol name.
397   GOFFData[GOFF::RecordLength * 2 + 72] = (char)0xC8; // Symbol name is Hello.
398   GOFFData[GOFF::RecordLength * 2 + 73] = (char)0x85;
399   GOFFData[GOFF::RecordLength * 2 + 74] = (char)0x93;
400   GOFFData[GOFF::RecordLength * 2 + 75] = (char)0x93;
401   GOFFData[GOFF::RecordLength * 2 + 76] = (char)0x96;
402 
403   // END record.
404   GOFFData[GOFF::RecordLength * 3] = (char)0x03;
405   GOFFData[GOFF::RecordLength * 3 + 1] = (char)0x40;
406 
407   StringRef Data(GOFFData, GOFF::RecordLength * 4);
408 
409   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
410       object::ObjectFile::createGOFFObjectFile(
411           MemoryBufferRef(Data, "dummyGOFF"));
412 
413   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
414 
415   GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
416 
417   for (SymbolRef Symbol : GOFFObj->symbols()) {
418     Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
419     ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
420     StringRef SymbolName = SymbolNameOrErr.get();
421     EXPECT_EQ(SymbolName, "Hello");
422   }
423 }
424 
425 TEST(GOFFObjectFileTest, InvalidSymbolType) {
426   char GOFFData[GOFF::RecordLength * 3] = {0x00};
427 
428   // HDR record.
429   GOFFData[0] = (char)0x03;
430   GOFFData[1] = (char)0xF0;
431 
432   // ESD record.
433   GOFFData[GOFF::RecordLength] = (char)0x03;
434   GOFFData[GOFF::RecordLength + 3] = (char)0x05;
435   GOFFData[GOFF::RecordLength + 7] = (char)0x01;
436   GOFFData[GOFF::RecordLength + 11] = (char)0x01;
437   GOFFData[GOFF::RecordLength + 71] = (char)0x01; // Size of symbol name.
438   GOFFData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name.
439 
440   // END record.
441   GOFFData[GOFF::RecordLength * 2] = (char)0x03;
442   GOFFData[GOFF::RecordLength * 2 + 1] = (char)0x40;
443 
444   StringRef Data(GOFFData, GOFF::RecordLength * 3);
445 
446   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
447       object::ObjectFile::createGOFFObjectFile(
448           MemoryBufferRef(Data, "dummyGOFF"));
449 
450   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
451 
452   GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
453 
454   for (SymbolRef Symbol : GOFFObj->symbols()) {
455     Expected<SymbolRef::Type> SymbolType = Symbol.getType();
456     EXPECT_THAT_EXPECTED(
457         SymbolType,
458         FailedWithMessage("ESD record 1 has invalid symbol type 0x05"));
459 
460     Expected<section_iterator> SymSI = Symbol.getSection();
461     ASSERT_THAT_EXPECTED(
462         SymSI,
463         FailedWithMessage(
464             "symbol with ESD id 1 refers to invalid section with ESD id 1"));
465   }
466 }
467 
468 TEST(GOFFObjectFileTest, InvalidERSymbolType) {
469   char GOFFData[GOFF::RecordLength * 3] = {0x00};
470 
471   // HDR record.
472   GOFFData[0] = (char)0x03;
473   GOFFData[1] = (char)0xF0;
474 
475   // ESD record.
476   GOFFData[GOFF::RecordLength] = (char)0x03;
477   GOFFData[GOFF::RecordLength + 3] = (char)0x04;
478   GOFFData[GOFF::RecordLength + 7] = (char)0x01;
479   GOFFData[GOFF::RecordLength + 11] = (char)0x01;
480   GOFFData[GOFF::RecordLength + 63] = (char)0x03; // Unknown executable type.
481   GOFFData[GOFF::RecordLength + 71] = (char)0x01; // Size of symbol name.
482   GOFFData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name.
483 
484   // END record.
485   GOFFData[GOFF::RecordLength * 2] = (char)0x03;
486   GOFFData[GOFF::RecordLength * 2 + 1] = (char)0x40;
487 
488   StringRef Data(GOFFData, GOFF::RecordLength * 3);
489 
490   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
491       object::ObjectFile::createGOFFObjectFile(
492           MemoryBufferRef(Data, "dummyGOFF"));
493 
494   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
495 
496   GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
497 
498   for (SymbolRef Symbol : GOFFObj->symbols()) {
499     Expected<SymbolRef::Type> SymbolType = Symbol.getType();
500     EXPECT_THAT_EXPECTED(
501         SymbolType,
502         FailedWithMessage("ESD record 1 has unknown Executable type 0x03"));
503   }
504 }
505 
506 TEST(GOFFObjectFileTest, TXTConstruct) {
507   char GOFFData[GOFF::RecordLength * 6] = {};
508 
509   // HDR record.
510   GOFFData[0] = (char)0x03;
511   GOFFData[1] = (char)0xF0;
512   GOFFData[50] = (char)0x01;
513 
514   // ESD record.
515   GOFFData[GOFF::RecordLength] = (char)0x03;
516   GOFFData[GOFF::RecordLength + 7] = (char)0x01;  // ESDID.
517   GOFFData[GOFF::RecordLength + 71] = (char)0x05; // Size of symbol name.
518   GOFFData[GOFF::RecordLength + 72] = (char)0xa5; // Symbol name is v.
519   GOFFData[GOFF::RecordLength + 73] = (char)0x81; // Symbol name is a.
520   GOFFData[GOFF::RecordLength + 74] = (char)0x99; // Symbol name is r.
521   GOFFData[GOFF::RecordLength + 75] = (char)0x7b; // Symbol name is #.
522   GOFFData[GOFF::RecordLength + 76] = (char)0x83; // Symbol name is c.
523 
524   // ESD record.
525   GOFFData[GOFF::RecordLength * 2] = (char)0x03;
526   GOFFData[GOFF::RecordLength * 2 + 3] = (char)0x01;
527   GOFFData[GOFF::RecordLength * 2 + 7] = (char)0x02;  // ESDID.
528   GOFFData[GOFF::RecordLength * 2 + 11] = (char)0x01; // Parent ESDID.
529   GOFFData[GOFF::RecordLength * 2 + 27] = (char)0x08; // Length.
530   GOFFData[GOFF::RecordLength * 2 + 40] = (char)0x01; // Name Space ID.
531   GOFFData[GOFF::RecordLength * 2 + 41] = (char)0x80;
532   GOFFData[GOFF::RecordLength * 2 + 60] = (char)0x04; // Size of symbol name.
533   GOFFData[GOFF::RecordLength * 2 + 61] = (char)0x04; // Size of symbol name.
534   GOFFData[GOFF::RecordLength * 2 + 63] = (char)0x0a; // Size of symbol name.
535   GOFFData[GOFF::RecordLength * 2 + 66] = (char)0x03; // Size of symbol name.
536   GOFFData[GOFF::RecordLength * 2 + 71] = (char)0x08; // Size of symbol name.
537   GOFFData[GOFF::RecordLength * 2 + 72] = (char)0xc3; // Symbol name is c.
538   GOFFData[GOFF::RecordLength * 2 + 73] = (char)0x6d; // Symbol name is _.
539   GOFFData[GOFF::RecordLength * 2 + 74] = (char)0xc3; // Symbol name is c.
540   GOFFData[GOFF::RecordLength * 2 + 75] = (char)0xd6; // Symbol name is o.
541   GOFFData[GOFF::RecordLength * 2 + 76] = (char)0xc4; // Symbol name is D.
542   GOFFData[GOFF::RecordLength * 2 + 77] = (char)0xc5; // Symbol name is E.
543   GOFFData[GOFF::RecordLength * 2 + 78] = (char)0xf6; // Symbol name is 6.
544   GOFFData[GOFF::RecordLength * 2 + 79] = (char)0xf4; // Symbol name is 4.
545 
546   // ESD record.
547   GOFFData[GOFF::RecordLength * 3] = (char)0x03;
548   GOFFData[GOFF::RecordLength * 3 + 3] = (char)0x02;
549   GOFFData[GOFF::RecordLength * 3 + 7] = (char)0x03;  // ESDID.
550   GOFFData[GOFF::RecordLength * 3 + 11] = (char)0x02; // Parent ESDID.
551   GOFFData[GOFF::RecordLength * 3 + 71] = (char)0x05; // Size of symbol name.
552   GOFFData[GOFF::RecordLength * 3 + 72] = (char)0xa5; // Symbol name is v.
553   GOFFData[GOFF::RecordLength * 3 + 73] = (char)0x81; // Symbol name is a.
554   GOFFData[GOFF::RecordLength * 3 + 74] = (char)0x99; // Symbol name is r.
555   GOFFData[GOFF::RecordLength * 3 + 75] = (char)0x7b; // Symbol name is #.
556   GOFFData[GOFF::RecordLength * 3 + 76] = (char)0x83; // Symbol name is c.
557 
558   // TXT record.
559   GOFFData[GOFF::RecordLength * 4] = (char)0x03;
560   GOFFData[GOFF::RecordLength * 4 + 1] = (char)0x10;
561   GOFFData[GOFF::RecordLength * 4 + 7] = (char)0x02;
562   GOFFData[GOFF::RecordLength * 4 + 23] = (char)0x08; // Data Length.
563   GOFFData[GOFF::RecordLength * 4 + 24] = (char)0x12;
564   GOFFData[GOFF::RecordLength * 4 + 25] = (char)0x34;
565   GOFFData[GOFF::RecordLength * 4 + 26] = (char)0x56;
566   GOFFData[GOFF::RecordLength * 4 + 27] = (char)0x78;
567   GOFFData[GOFF::RecordLength * 4 + 28] = (char)0x9a;
568   GOFFData[GOFF::RecordLength * 4 + 29] = (char)0xbc;
569   GOFFData[GOFF::RecordLength * 4 + 30] = (char)0xde;
570   GOFFData[GOFF::RecordLength * 4 + 31] = (char)0xf0;
571 
572   // END record.
573   GOFFData[GOFF::RecordLength * 5] = (char)0x03;
574   GOFFData[GOFF::RecordLength * 5 + 1] = (char)0x40;
575   GOFFData[GOFF::RecordLength * 5 + 11] = (char)0x06;
576 
577   StringRef Data(GOFFData, GOFF::RecordLength * 6);
578 
579   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
580       object::ObjectFile::createGOFFObjectFile(
581           MemoryBufferRef(Data, "dummyGOFF"));
582 
583   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
584 
585   GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
586   auto Symbols = GOFFObj->symbols();
587   ASSERT_EQ(std::distance(Symbols.begin(), Symbols.end()), 1);
588   SymbolRef Symbol = *Symbols.begin();
589   Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
590   ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
591   StringRef SymbolName = SymbolNameOrErr.get();
592   EXPECT_EQ(SymbolName, "var#c");
593 
594   auto Sections = GOFFObj->sections();
595   ASSERT_EQ(std::distance(Sections.begin(), Sections.end()), 1);
596   SectionRef Section = *Sections.begin();
597   Expected<StringRef> SectionContent = Section.getContents();
598   ASSERT_THAT_EXPECTED(SectionContent, Succeeded());
599   StringRef Contents = SectionContent.get();
600   EXPECT_EQ(Contents, "\x12\x34\x56\x78\x9a\xbc\xde\xf0");
601 }
602