1 //===- lld/unittest/MachOTests/MachONormalizedFileToAtomsTests.cpp --------===//
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 "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
10 #include "lld/Core/Atom.h"
11 #include "lld/Core/DefinedAtom.h"
12 #include "lld/Core/File.h"
13 #include "lld/Core/UndefinedAtom.h"
14 #include "lld/ReaderWriter/MachOLinkingContext.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/BinaryFormat/MachO.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/YAMLTraits.h"
19 #include "gtest/gtest.h"
20 #include <cstdint>
21 #include <memory>
22
23 using namespace lld::mach_o::normalized;
24 using namespace llvm::MachO;
25
TEST(ToAtomsTest,empty_obj_x86_64)26 TEST(ToAtomsTest, empty_obj_x86_64) {
27 NormalizedFile f;
28 f.arch = lld::MachOLinkingContext::arch_x86_64;
29 llvm::Expected<std::unique_ptr<const lld::File>> atom_f =
30 normalizedToAtoms(f, "", false);
31 EXPECT_FALSE(!atom_f);
32 EXPECT_EQ(0U, (*atom_f)->defined().size());
33 }
34
TEST(ToAtomsTest,basic_obj_x86_64)35 TEST(ToAtomsTest, basic_obj_x86_64) {
36 NormalizedFile f;
37 f.arch = lld::MachOLinkingContext::arch_x86_64;
38 Section textSection;
39 static const uint8_t contentBytes[] = { 0x90, 0xC3, 0xC3, 0xC4 };
40 const unsigned contentSize = sizeof(contentBytes) / sizeof(contentBytes[0]);
41 textSection.content = llvm::makeArrayRef(contentBytes, contentSize);
42 f.sections.push_back(textSection);
43 Symbol fooSymbol;
44 fooSymbol.name = "_foo";
45 fooSymbol.type = N_SECT;
46 fooSymbol.scope = N_EXT;
47 fooSymbol.sect = 1;
48 fooSymbol.value = 0;
49 f.globalSymbols.push_back(fooSymbol);
50 Symbol barSymbol;
51 barSymbol.name = "_bar";
52 barSymbol.type = N_SECT;
53 barSymbol.scope = N_EXT;
54 barSymbol.sect = 1;
55 barSymbol.value = 2;
56 f.globalSymbols.push_back(barSymbol);
57 Symbol undefSym;
58 undefSym.name = "_undef";
59 undefSym.type = N_UNDF;
60 f.undefinedSymbols.push_back(undefSym);
61 Symbol bazSymbol;
62 bazSymbol.name = "_baz";
63 bazSymbol.type = N_SECT;
64 bazSymbol.scope = N_EXT | N_PEXT;
65 bazSymbol.sect = 1;
66 bazSymbol.value = 3;
67 f.localSymbols.push_back(bazSymbol);
68
69 llvm::Expected<std::unique_ptr<const lld::File>> atom_f =
70 normalizedToAtoms(f, "", false);
71 EXPECT_FALSE(!atom_f);
72 const lld::File &file = **atom_f;
73 EXPECT_EQ(3U, file.defined().size());
74 auto it = file.defined().begin();
75 const lld::DefinedAtom *atom1 = *it;
76 ++it;
77 const lld::DefinedAtom *atom2 = *it;
78 ++it;
79 const lld::DefinedAtom *atom3 = *it;
80 const lld::UndefinedAtom *atom4 = *file.undefined().begin();
81 EXPECT_TRUE(atom1->name().equals("_foo"));
82 EXPECT_EQ(2U, atom1->rawContent().size());
83 EXPECT_EQ(0x90, atom1->rawContent()[0]);
84 EXPECT_EQ(0xC3, atom1->rawContent()[1]);
85 EXPECT_EQ(lld::Atom::scopeGlobal, atom1->scope());
86
87 EXPECT_TRUE(atom2->name().equals("_bar"));
88 EXPECT_EQ(1U, atom2->rawContent().size());
89 EXPECT_EQ(0xC3, atom2->rawContent()[0]);
90 EXPECT_EQ(lld::Atom::scopeGlobal, atom2->scope());
91
92 EXPECT_TRUE(atom3->name().equals("_baz"));
93 EXPECT_EQ(1U, atom3->rawContent().size());
94 EXPECT_EQ(0xC4, atom3->rawContent()[0]);
95 EXPECT_EQ(lld::Atom::scopeLinkageUnit, atom3->scope());
96
97 EXPECT_TRUE(atom4->name().equals("_undef"));
98 EXPECT_EQ(lld::Atom::definitionUndefined, atom4->definition());
99 }
100
TEST(ToAtomsTest,reservedUnitLength)101 TEST(ToAtomsTest, reservedUnitLength) {
102 static const uint8_t debugInfoWithReservedLengthContent[12] = {
103 0xf0, 0xff, 0xff, 0xff // Reserved length value
104 };
105 static const uint8_t debugInfoWithValidBigLengthContent[12] = {
106 0xef, 0xff, 0xff, 0xff, // The maximum valid length value for DWARF32
107 0x00, 0x00 // Wrong version
108 };
109 static const uint8_t dummyContent[] = {0x00};
110
111 NormalizedFile fReservedLength, fValidBigLength;
112 fReservedLength.arch = lld::MachOLinkingContext::arch_x86;
113 fValidBigLength.arch = lld::MachOLinkingContext::arch_x86;
114 Section section;
115 section.segmentName = "__DWARF";
116 section.sectionName = "__debug_info";
117 section.content = llvm::makeArrayRef(debugInfoWithReservedLengthContent);
118 fReservedLength.sections.push_back(section);
119 section.content = llvm::makeArrayRef(debugInfoWithValidBigLengthContent);
120 fValidBigLength.sections.push_back(section);
121 section.sectionName = "__debug_abbrev";
122 section.content = llvm::makeArrayRef(dummyContent);
123 fReservedLength.sections.push_back(section);
124 fValidBigLength.sections.push_back(section);
125 section.sectionName = "__debug_str";
126 fReservedLength.sections.push_back(section);
127 fValidBigLength.sections.push_back(section);
128
129 auto resultReservedLength = normalizedToAtoms(fReservedLength, "foo", false);
130 auto resultValidBigLength = normalizedToAtoms(fValidBigLength, "foo", false);
131
132 // Both cases should return errors, but different.
133 ASSERT_FALSE(resultReservedLength);
134 ASSERT_FALSE(resultValidBigLength);
135
136 EXPECT_STREQ("Malformed DWARF in foo",
137 toString(resultReservedLength.takeError()).c_str());
138 EXPECT_STREQ("Unsupported DWARF version in foo",
139 toString(resultValidBigLength.takeError()).c_str());
140 }
141