Skip to content

Commit eaef074

Browse files
committed
MachO: support N_INDR aliases in assembly files.
This makes LLVM create N_INDR aliases (to be resolved by the linker) when appropriate. rdar://problem/15125513 llvm-svn: 209894
1 parent 6bfdaf5 commit eaef074

File tree

7 files changed

+168
-13
lines changed

7 files changed

+168
-13
lines changed

llvm/include/llvm/MC/MCMachObjectWriter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ class MachObjectWriter : public MCObjectWriter {
111111

112112
/// @}
113113

114+
MachSymbolData *findSymbolData(const MCSymbol &Sym);
115+
114116
public:
115117
MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
116118
bool _IsLittleEndian)

llvm/include/llvm/Object/SymbolicFile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class BasicSymbolRef {
8686
SF_Weak = 1U << 2, // Weak symbol
8787
SF_Absolute = 1U << 3, // Absolute symbol
8888
SF_Common = 1U << 4, // Symbol has common linkage
89+
SF_Indirect = 1U << 5,
8990
SF_FormatSpecific = 1U << 5 // Specific to the object file format
9091
// (e.g. section symbols)
9192
};

llvm/lib/MC/MachObjectWriter.cpp

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -303,20 +303,50 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
303303
assert(OS.tell() - Start == sizeof(MachO::dysymtab_command));
304304
}
305305

306+
MachObjectWriter::MachSymbolData *
307+
MachObjectWriter::findSymbolData(const MCSymbol &Sym) {
308+
for (auto &Entry : LocalSymbolData)
309+
if (&Entry.SymbolData->getSymbol() == &Sym)
310+
return &Entry;
311+
312+
for (auto &Entry : ExternalSymbolData)
313+
if (&Entry.SymbolData->getSymbol() == &Sym)
314+
return &Entry;
315+
316+
for (auto &Entry : UndefinedSymbolData)
317+
if (&Entry.SymbolData->getSymbol() == &Sym)
318+
return &Entry;
319+
320+
return nullptr;
321+
}
322+
306323
void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
307324
const MCAsmLayout &Layout) {
308325
MCSymbolData &Data = *MSD.SymbolData;
309-
const MCSymbol &Symbol = Data.getSymbol();
326+
const MCSymbol *Symbol = &Data.getSymbol();
327+
const MCSymbol *AliasedSymbol = &Symbol->AliasedSymbol();
328+
uint8_t SectionIndex = MSD.SectionIndex;
310329
uint8_t Type = 0;
311330
uint16_t Flags = Data.getFlags();
312331
uint64_t Address = 0;
332+
bool IsAlias = Symbol != AliasedSymbol;
333+
334+
MachSymbolData *AliaseeInfo;
335+
if (IsAlias) {
336+
AliaseeInfo = findSymbolData(*AliasedSymbol);
337+
if (AliaseeInfo)
338+
SectionIndex = AliaseeInfo->SectionIndex;
339+
Symbol = AliasedSymbol;
340+
}
313341

314342
// Set the N_TYPE bits. See <mach-o/nlist.h>.
315343
//
316344
// FIXME: Are the prebound or indirect fields possible here?
317-
if (Symbol.isUndefined())
345+
if (IsAlias && Symbol->isUndefined())
346+
Type = MachO::N_INDR;
347+
else if (Symbol->isUndefined())
318348
Type = MachO::N_UNDF;
319-
else if (Symbol.isAbsolute())
349+
else if (Symbol->isAbsolute())
320350
Type = MachO::N_ABS;
321351
else
322352
Type = MachO::N_SECT;
@@ -327,13 +357,15 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
327357
Type |= MachO::N_PEXT;
328358

329359
// Set external bit.
330-
if (Data.isExternal() || Symbol.isUndefined())
360+
if (Data.isExternal() || (!IsAlias && Symbol->isUndefined()))
331361
Type |= MachO::N_EXT;
332362

333363
// Compute the symbol address.
334-
if (Symbol.isDefined()) {
364+
if (IsAlias && Symbol->isUndefined())
365+
Address = AliaseeInfo->StringIndex;
366+
else if (Symbol->isDefined())
335367
Address = getSymbolAddress(&Data, Layout);
336-
} else if (Data.isCommon()) {
368+
else if (Data.isCommon()) {
337369
// Common symbols are encoded with the size in the address
338370
// field, and their alignment in the flags.
339371
Address = Data.getCommonSize();
@@ -344,21 +376,21 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
344376
assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
345377
if (Log2Size > 15)
346378
report_fatal_error("invalid 'common' alignment '" +
347-
Twine(Align) + "' for '" + Symbol.getName() + "'",
379+
Twine(Align) + "' for '" + Symbol->getName() + "'",
348380
false);
349381
// FIXME: Keep this mask with the SymbolFlags enumeration.
350382
Flags = (Flags & 0xF0FF) | (Log2Size << 8);
351383
}
352384
}
353385

354-
if (Layout.getAssembler().isThumbFunc(&Symbol))
386+
if (Layout.getAssembler().isThumbFunc(Symbol))
355387
Flags |= SF_ThumbFunc;
356388

357389
// struct nlist (12 bytes)
358390

359391
Write32(MSD.StringIndex);
360392
Write8(Type);
361-
Write8(MSD.SectionIndex);
393+
Write8(SectionIndex);
362394

363395
// The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
364396
// value.

llvm/lib/Object/MachOObjectFile.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,9 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
584584
if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
585585
Result |= SymbolRef::SF_Undefined;
586586

587+
if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
588+
Result |= SymbolRef::SF_Indirect;
589+
587590
if (MachOType & MachO::N_STAB)
588591
Result |= SymbolRef::SF_FormatSpecific;
589592

llvm/test/MC/MachO/aliased-symbols.s

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// RUN: llvm-mc -triple thumbv7m-apple-darwin-eabi %s -filetype=obj -o %t
2+
// RUN: llvm-readobj -symbols %t | FileCheck %s
3+
4+
.data
5+
var1 = var2
6+
.long var1
7+
.long var2
8+
.long var2 + 4
9+
defined_early:
10+
.long 0
11+
12+
alias_to_early = defined_early
13+
alias_to_late = defined_late
14+
15+
defined_late:
16+
.long 0
17+
18+
.global extern_test
19+
extern_test = var2
20+
21+
alias_to_local = Ltmp0
22+
Ltmp0:
23+
24+
// CHECK: Symbols [
25+
26+
// defined_early was defined. Actually has value 0xc.
27+
// CHECK: Symbol {
28+
// CHECK-NEXT: Name: defined_early
29+
// CHECK-NEXT: Type: Section (0xE)
30+
// CHECK-NEXT: Section: __data (0x2)
31+
// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
32+
// CHECK-NEXT: Flags [ (0x0)
33+
// CHECK-NEXT: ]
34+
// CHECK-NEXT: Value: 0x[[DEFINED_EARLY:[0-9A-F]+]]
35+
// CHECK-NEXT: }
36+
37+
// alias_to_early was an alias to defined_early. But we can resolve it.
38+
// CHECK: Symbol {
39+
// CHECK-NEXT: Name: alias_to_early
40+
// CHECK-NEXT: Type: Section (0xE)
41+
// CHECK-NEXT: Section: __data (0x2)
42+
// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
43+
// CHECK-NEXT: Flags [ (0x0)
44+
// CHECK-NEXT: ]
45+
// CHECK-NEXT: Value: 0x[[DEFINED_EARLY]]
46+
// CHECK-NEXT: }
47+
48+
// defined_late was defined. Just after defined_early.
49+
// CHECK: Symbol {
50+
// CHECK-NEXT: Name: defined_late
51+
// CHECK-NEXT: Type: Section (0xE)
52+
// CHECK-NEXT: Section: __data (0x2)
53+
// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
54+
// CHECK-NEXT: Flags [ (0x0)
55+
// CHECK-NEXT: ]
56+
// CHECK-NEXT: Value: 0x[[DEFINED_LATE:[0-9A-F]+]]
57+
// CHECK-NEXT: }
58+
59+
// alias_to_late was an alias to defined_late. But we can resolve it.
60+
// CHECK: Symbol {
61+
// CHECK-NEXT: Name: alias_to_late
62+
// CHECK-NEXT: Type: Section (0xE)
63+
// CHECK-NEXT: Section: __data (0x2)
64+
// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
65+
// CHECK-NEXT: Flags [ (0x0)
66+
// CHECK-NEXT: ]
67+
// CHECK-NEXT: Value: 0x[[DEFINED_LATE]]
68+
// CHECK-NEXT: }
69+
70+
// alias_to_local is an alias, but what it points to has no
71+
// MachO representation. We must resolve it.
72+
// CHECK: Symbol {
73+
// CHECK-NEXT: Name: alias_to_local (37)
74+
// CHECK-NEXT: Type: Section (0xE)
75+
// CHECK-NEXT: Section: (0x0)
76+
// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
77+
// CHECK-NEXT: Flags [ (0x0)
78+
// CHECK-NEXT: ]
79+
// CHECK-NEXT: Value: 0x14
80+
// CHECK-NEXT: }
81+
82+
// extern_test was a pure alias to the unknown "var2".
83+
// N_INDR and Extern.
84+
// CHECK: Name: extern_test
85+
// CHECK-NEXT: Extern
86+
// CHECK-NEXT: Type: Indirect (0xA)
87+
// CHECK-NEXT: Section: (0x0)
88+
// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
89+
// CHECK-NEXT: Flags [ (0x0)
90+
// CHECK-NEXT: ]
91+
// CHECK-NEXT: Value: 0x[[VAR2_STRINGINDEX:[0-9a-f]+]]
92+
// CHECK-NEXT: }
93+
94+
// var1 was another alias to an unknown variable. Not extern this time.
95+
// CHECK: Symbol {
96+
// CHECK-NEXT: Name: var1 (1)
97+
// CHECK-NEXT: Type: Indirect (0xA)
98+
// CHECK-NEXT: Section: (0x0)
99+
// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
100+
// CHECK-NEXT: Flags [ (0x0)
101+
// CHECK-NEXT: ]
102+
// CHECK-NEXT: Value: 0x[[VAR2_STRINGINDEX]]
103+
// CHECK-NEXT: }
104+
105+
// var2 was a normal undefined (extern) symbol.
106+
// CHECK: Symbol {
107+
// CHECK-NEXT: Name: var2
108+
// CHECK-NEXT: Extern
109+
// CHECK-NEXT: Type: Undef (0x0)
110+
// CHECK-NEXT: Section: (0x0)
111+
// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
112+
// CHECK-NEXT: Flags [ (0x0)
113+
// CHECK-NEXT: ]
114+
// CHECK-NEXT: Value: 0x0
115+
// CHECK-NEXT: }

llvm/test/MC/MachO/variable-exprs.s

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,10 @@ Lt0_x = Lt0_a - Lt0_b
202202
// CHECK-I386: ),
203203
// CHECK-I386: # Symbol 8
204204
// CHECK-I386: (('n_strx', 1)
205-
// CHECK-I386: ('n_type', 0x1)
205+
// CHECK-I386: ('n_type', 0xb)
206206
// CHECK-I386: ('n_sect', 0)
207207
// CHECK-I386: ('n_desc', 0)
208-
// CHECK-I386: ('n_value', 0)
208+
// CHECK-I386: ('n_value', 4)
209209
// CHECK-I386: ('_string', 'd2')
210210
// CHECK-I386: ),
211211
// CHECK-I386: # Symbol 9
@@ -403,10 +403,10 @@ Lt0_x = Lt0_a - Lt0_b
403403
// CHECK-X86_64: ),
404404
// CHECK-X86_64: # Symbol 8
405405
// CHECK-X86_64: (('n_strx', 1)
406-
// CHECK-X86_64: ('n_type', 0x1)
406+
// CHECK-X86_64: ('n_type', 0xb)
407407
// CHECK-X86_64: ('n_sect', 0)
408408
// CHECK-X86_64: ('n_desc', 0)
409-
// CHECK-X86_64: ('n_value', 0)
409+
// CHECK-X86_64: ('n_value', 4)
410410
// CHECK-X86_64: ('_string', 'd2')
411411
// CHECK-X86_64: ),
412412
// CHECK-X86_64: # Symbol 9

llvm/tools/llvm-nm/llvm-nm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
395395
switch (NType & MachO::N_TYPE) {
396396
case MachO::N_ABS:
397397
return 's';
398+
case MachO::N_INDR:
399+
return 'i';
398400
case MachO::N_SECT: {
399401
section_iterator Sec = Obj.section_end();
400402
Obj.getSymbolSection(Symb, Sec);

0 commit comments

Comments
 (0)