Skip to content

Commit 41cbb64

Browse files
committed
[llvm-objcopy] Add support of symbol modification flags for MachO
This patch adds support of the following llvm-objcopy flags for MachO: - --skip-symbol - --localize-symbol - --globalize-symbol - --keep-global-symbol Code in `updateAndRemoveSymbols` for MachO is kept similar to its version for ELF.
1 parent eaf67e0 commit 41cbb64

File tree

8 files changed

+665
-11
lines changed

8 files changed

+665
-11
lines changed

llvm/lib/ObjCopy/ConfigManager.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,9 @@ Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
3636

3737
Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
3838
if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
39-
!Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
39+
!Common.SymbolsPrefixRemove.empty() ||
4040
!Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
41-
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
42-
!Common.SymbolsToLocalize.empty() ||
43-
!Common.SymbolsToKeepGlobal.empty() || !Common.SectionsToRename.empty() ||
41+
!Common.SymbolsToKeep.empty() || !Common.SectionsToRename.empty() ||
4442
!Common.UnneededSymbolsToRemove.empty() ||
4543
!Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
4644
!Common.SetSectionType.empty() || Common.ExtractDWO ||

llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,38 @@ static void markSymbols(const CommonConfig &, Object &Obj) {
9393
static void updateAndRemoveSymbols(const CommonConfig &Config,
9494
const MachOConfig &MachOConfig,
9595
Object &Obj) {
96-
for (SymbolEntry &Sym : Obj.SymTable) {
97-
// Weaken symbols first to match ELFObjcopy behavior.
98-
bool IsExportedAndDefined =
99-
(Sym.n_type & llvm::MachO::N_EXT) &&
100-
(Sym.n_type & llvm::MachO::N_TYPE) != llvm::MachO::N_UNDF;
101-
if (IsExportedAndDefined &&
96+
Obj.SymTable.updateSymbols([&](SymbolEntry &Sym) {
97+
if (Config.SymbolsToSkip.matches(Sym.Name))
98+
return;
99+
100+
if (!Sym.isUndefinedSymbol() && Config.SymbolsToLocalize.matches(Sym.Name))
101+
Sym.n_type &= ~llvm::MachO::N_EXT;
102+
103+
// Note: these two globalize flags have very similar names but different
104+
// meanings:
105+
//
106+
// --globalize-symbol: promote a symbol to global
107+
// --keep-global-symbol: all symbols except for these should be made local
108+
//
109+
// If --globalize-symbol is specified for a given symbol, it will be
110+
// global in the output file even if it is not included via
111+
// --keep-global-symbol. Because of that, make sure to check
112+
// --globalize-symbol second.
113+
if (!Sym.isUndefinedSymbol() && !Config.SymbolsToKeepGlobal.empty() &&
114+
!Config.SymbolsToKeepGlobal.matches(Sym.Name))
115+
Sym.n_type &= ~llvm::MachO::N_EXT;
116+
117+
if (!Sym.isUndefinedSymbol() && Config.SymbolsToGlobalize.matches(Sym.Name))
118+
Sym.n_type |= llvm::MachO::N_EXT;
119+
120+
if (Sym.isExternalSymbol() && !Sym.isUndefinedSymbol() &&
102121
(Config.Weaken || Config.SymbolsToWeaken.matches(Sym.Name)))
103122
Sym.n_desc |= llvm::MachO::N_WEAK_DEF;
104123

105124
auto I = Config.SymbolsToRename.find(Sym.Name);
106125
if (I != Config.SymbolsToRename.end())
107126
Sym.Name = std::string(I->getValue());
108-
}
127+
});
109128

110129
auto RemovePred = [&Config, &MachOConfig,
111130
&Obj](const std::unique_ptr<SymbolEntry> &N) {

llvm/lib/ObjCopy/MachO/MachOObject.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ SymbolEntry *SymbolTable::getSymbolByIndex(uint32_t Index) {
3333
static_cast<const SymbolTable *>(this)->getSymbolByIndex(Index));
3434
}
3535

36+
void SymbolTable::updateSymbols(function_ref<void(SymbolEntry &)> Callable) {
37+
for (auto &Sym : Symbols)
38+
Callable(*Sym);
39+
40+
// Partition symbols: local < defined external < undefined external.
41+
auto it_ext = std::stable_partition(
42+
std::begin(Symbols), std::end(Symbols),
43+
[](const auto &Sym) { return Sym->isLocalSymbol(); });
44+
std::stable_partition(it_ext, std::end(Symbols), [](const auto &Sym) {
45+
return !Sym->isUndefinedSymbol();
46+
});
47+
}
48+
3649
void SymbolTable::removeSymbols(
3750
function_ref<bool(const std::unique_ptr<SymbolEntry> &)> ToRemove) {
3851
llvm::erase_if(Symbols, ToRemove);

llvm/lib/ObjCopy/MachO/MachOObject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ struct SymbolTable {
142142

143143
const SymbolEntry *getSymbolByIndex(uint32_t Index) const;
144144
SymbolEntry *getSymbolByIndex(uint32_t Index);
145+
void updateSymbols(function_ref<void(SymbolEntry &)> Callable);
145146
void removeSymbols(
146147
function_ref<bool(const std::unique_ptr<SymbolEntry> &)> ToRemove);
147148
};
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: llvm-objcopy --wildcard --globalize-symbol="*" %t %t.copy
3+
# RUN: llvm-readobj --symbols %t.copy | FileCheck %s
4+
5+
# CHECK: Symbols [
6+
# CHECK-NEXT: Symbol {
7+
# CHECK-NEXT: Name: _PrivateSymbol
8+
# CHECK-NEXT: Extern
9+
# CHECK-NEXT: Type: Section (0xE)
10+
# CHECK-NEXT: Section: __text (0x1)
11+
# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
12+
# CHECK-NEXT: Flags [ (0x0)
13+
# CHECK-NEXT: ]
14+
# CHECK-NEXT: Value: 0x1
15+
# CHECK-NEXT: }
16+
# CHECK-NEXT: Symbol {
17+
# CHECK-NEXT: Name: _PrivateExternalSymbol
18+
# CHECK-NEXT: PrivateExtern
19+
# CHECK-NEXT: Extern
20+
# CHECK-NEXT: Type: Section (0xE)
21+
# CHECK-NEXT: Section: __text (0x1)
22+
# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
23+
# CHECK-NEXT: Flags [ (0x0)
24+
# CHECK-NEXT: ]
25+
# CHECK-NEXT: Value: 0x2
26+
# CHECK-NEXT: }
27+
# CHECK-NEXT: Symbol {
28+
# CHECK-NEXT: Name: _CommonSymbol
29+
# CHECK-NEXT: Extern
30+
# CHECK-NEXT: Type: Section (0xE)
31+
# CHECK-NEXT: Section: __text (0x1)
32+
# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
33+
# CHECK-NEXT: Flags [ (0x0)
34+
# CHECK-NEXT: ]
35+
# CHECK-NEXT: Value: 0x3
36+
# CHECK-NEXT: }
37+
# CHECK-NEXT: Symbol {
38+
# CHECK-NEXT: Name: _UndefinedExternalSymbol
39+
# CHECK-NEXT: Extern
40+
# CHECK-NEXT: Type: Undef (0x0)
41+
# CHECK-NEXT: Section: (0x0)
42+
# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
43+
# CHECK-NEXT: Flags [ (0x0)
44+
# CHECK-NEXT: ]
45+
# CHECK-NEXT: Value: 0x0
46+
# CHECK-NEXT: }
47+
# CHECK-NEXT: ]
48+
49+
--- !mach-o
50+
FileHeader:
51+
magic: 0xFEEDFACF
52+
cputype: 0x100000C
53+
cpusubtype: 0x0
54+
filetype: 0x2
55+
ncmds: 4
56+
sizeofcmds: 328
57+
flags: 0x200085
58+
reserved: 0x0
59+
LoadCommands:
60+
- cmd: LC_SEGMENT_64
61+
cmdsize: 152
62+
segname: __TEXT
63+
vmaddr: 4294967296
64+
vmsize: 4096
65+
fileoff: 0
66+
filesize: 4096
67+
maxprot: 5
68+
initprot: 5
69+
nsects: 1
70+
flags: 0
71+
Sections:
72+
- sectname: __text
73+
segname: __TEXT
74+
addr: 0x100000FF8
75+
size: 8
76+
offset: 0xFF8
77+
align: 2
78+
reloff: 0x0
79+
nreloc: 0
80+
flags: 0x80000400
81+
reserved1: 0x0
82+
reserved2: 0x0
83+
reserved3: 0x0
84+
content: 00008052C0035FD6
85+
- cmd: LC_SEGMENT_64
86+
cmdsize: 72
87+
segname: __LINKEDIT
88+
vmaddr: 4294971392
89+
vmsize: 4096
90+
fileoff: 4096
91+
filesize: 147
92+
maxprot: 1
93+
initprot: 1
94+
nsects: 0
95+
flags: 0
96+
- cmd: LC_SYMTAB
97+
cmdsize: 24
98+
symoff: 4096
99+
nsyms: 4
100+
stroff: 4164
101+
strsize: 79
102+
- cmd: LC_DYSYMTAB
103+
cmdsize: 80
104+
ilocalsym: 0
105+
nlocalsym: 1
106+
iextdefsym: 1
107+
nextdefsym: 1
108+
iundefsym: 1
109+
nundefsym: 1
110+
tocoff: 0
111+
ntoc: 0
112+
modtaboff: 0
113+
nmodtab: 0
114+
extrefsymoff: 0
115+
nextrefsyms: 0
116+
indirectsymoff: 0
117+
nindirectsyms: 0
118+
extreloff: 0
119+
nextrel: 0
120+
locreloff: 0
121+
nlocrel: 0
122+
LinkEditData:
123+
NameList:
124+
- n_strx: 2
125+
n_type: 0x0E
126+
n_sect: 1
127+
n_desc: 0
128+
n_value: 1
129+
- n_strx: 17
130+
n_type: 0x1E
131+
n_sect: 1
132+
n_desc: 0
133+
n_value: 2
134+
- n_strx: 40
135+
n_type: 0x0F
136+
n_sect: 1
137+
n_desc: 0
138+
n_value: 3
139+
- n_strx: 54
140+
n_type: 0x01
141+
n_sect: 0
142+
n_desc: 0
143+
n_value: 0
144+
StringTable:
145+
- ' '
146+
- _PrivateSymbol
147+
- _PrivateExternalSymbol
148+
- _CommonSymbol
149+
- _UndefinedExternalSymbol
150+
...

0 commit comments

Comments
 (0)