Skip to content

Commit a6e1b3c

Browse files
committed
[ObjectYAML][MachO] Add LC_FUNCTION_STARTS support
This adds support for encoding and decoding the LC_FUNCTION_STARTS load command payload. Differential Revision: https://reviews.llvm.org/D119205
1 parent c45c53b commit a6e1b3c

File tree

7 files changed

+237
-5
lines changed

7 files changed

+237
-5
lines changed

llvm/include/llvm/Object/MachO.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ class MachOObjectFile : public ObjectFile {
563563
ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;
564564
ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const;
565565
ArrayRef<uint8_t> getDyldInfoExportsTrie() const;
566+
SmallVector<uint64_t> getFunctionStarts() const;
566567
ArrayRef<uint8_t> getUuid() const;
567568

568569
StringRef getStringTableData() const;
@@ -689,6 +690,7 @@ class MachOObjectFile : public ObjectFile {
689690
const char *DataInCodeLoadCmd = nullptr;
690691
const char *LinkOptHintsLoadCmd = nullptr;
691692
const char *DyldInfoLoadCmd = nullptr;
693+
const char *FuncStartsLoadCmd = nullptr;
692694
const char *UuidLoadCmd = nullptr;
693695
bool HasPageZeroSegment = false;
694696
};

llvm/include/llvm/ObjectYAML/MachOYAML.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ struct LinkEditData {
122122
std::vector<NListEntry> NameList;
123123
std::vector<StringRef> StringTable;
124124
std::vector<yaml::Hex32> IndirectSymbols;
125+
std::vector<yaml::Hex64> FunctionStarts;
125126

126127
bool isEmpty() const;
127128
};

llvm/lib/Object/MachOObjectFile.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1303,7 +1303,6 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
13031303
}
13041304

13051305
const char *DyldIdLoadCmd = nullptr;
1306-
const char *FuncStartsLoadCmd = nullptr;
13071306
const char *SplitInfoLoadCmd = nullptr;
13081307
const char *CodeSignDrsLoadCmd = nullptr;
13091308
const char *CodeSignLoadCmd = nullptr;
@@ -4663,6 +4662,21 @@ ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
46634662
return makeArrayRef(Ptr, DyldInfo.export_size);
46644663
}
46654664

4665+
SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const {
4666+
if (!FuncStartsLoadCmd)
4667+
return {};
4668+
4669+
auto InfoOrErr =
4670+
getStructOrErr<MachO::linkedit_data_command>(*this, FuncStartsLoadCmd);
4671+
if (!InfoOrErr)
4672+
return {};
4673+
4674+
MachO::linkedit_data_command Info = InfoOrErr.get();
4675+
SmallVector<uint64_t, 8> FunctionStarts;
4676+
this->ReadULEB128s(Info.dataoff, FunctionStarts);
4677+
return std::move(FunctionStarts);
4678+
}
4679+
46664680
ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
46674681
if (!UuidLoadCmd)
46684682
return None;

llvm/lib/ObjectYAML/MachOEmitter.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class MachOWriter {
5555
void writeStringTable(raw_ostream &OS);
5656
void writeExportTrie(raw_ostream &OS);
5757
void writeDynamicSymbolTable(raw_ostream &OS);
58+
void writeFunctionStarts(raw_ostream &OS);
5859

5960
void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
6061
void ZeroToOffset(raw_ostream &OS, size_t offset);
@@ -484,6 +485,7 @@ void MachOWriter::writeLinkEditData(raw_ostream &OS) {
484485
MachO::dyld_info_command *DyldInfoOnlyCmd = nullptr;
485486
MachO::symtab_command *SymtabCmd = nullptr;
486487
MachO::dysymtab_command *DSymtabCmd = nullptr;
488+
MachO::linkedit_data_command *FunctionStartsCmd = nullptr;
487489
for (auto &LC : Obj.LoadCommands) {
488490
switch (LC.Data.load_command_data.cmd) {
489491
case MachO::LC_SYMTAB:
@@ -511,6 +513,11 @@ void MachOWriter::writeLinkEditData(raw_ostream &OS) {
511513
WriteQueue.push_back(std::make_pair(
512514
DSymtabCmd->indirectsymoff, &MachOWriter::writeDynamicSymbolTable));
513515
break;
516+
case MachO::LC_FUNCTION_STARTS:
517+
FunctionStartsCmd = &LC.Data.linkedit_data_command_data;
518+
WriteQueue.push_back(std::make_pair(FunctionStartsCmd->dataoff,
519+
&MachOWriter::writeFunctionStarts));
520+
break;
514521
}
515522
}
516523

@@ -569,6 +576,17 @@ void MachOWriter::writeDynamicSymbolTable(raw_ostream &OS) {
569576
sizeof(yaml::Hex32::BaseType));
570577
}
571578

579+
void MachOWriter::writeFunctionStarts(raw_ostream &OS) {
580+
uint64_t Addr = 0;
581+
for (uint64_t NextAddr : Obj.LinkEdit.FunctionStarts) {
582+
uint64_t Delta = NextAddr - Addr;
583+
encodeULEB128(Delta, OS);
584+
Addr = NextAddr;
585+
}
586+
587+
OS.write('\0');
588+
}
589+
572590
class UniversalWriter {
573591
public:
574592
UniversalWriter(yaml::YamlObjectFile &ObjectFile)

llvm/lib/ObjectYAML/MachOYAML.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ namespace llvm {
2626
MachOYAML::LoadCommand::~LoadCommand() = default;
2727

2828
bool MachOYAML::LinkEditData::isEmpty() const {
29-
return 0 ==
30-
RebaseOpcodes.size() + BindOpcodes.size() + WeakBindOpcodes.size() +
31-
LazyBindOpcodes.size() + ExportTrie.Children.size() +
32-
NameList.size() + StringTable.size();
29+
return 0 == RebaseOpcodes.size() + BindOpcodes.size() +
30+
WeakBindOpcodes.size() + LazyBindOpcodes.size() +
31+
ExportTrie.Children.size() + NameList.size() +
32+
StringTable.size() + FunctionStarts.size();
3333
}
3434

3535
namespace yaml {
@@ -165,6 +165,7 @@ void MappingTraits<MachOYAML::LinkEditData>::mapping(
165165
IO.mapOptional("NameList", LinkEditData.NameList);
166166
IO.mapOptional("StringTable", LinkEditData.StringTable);
167167
IO.mapOptional("IndirectSymbols", LinkEditData.IndirectSymbols);
168+
IO.mapOptional("FunctionStarts", LinkEditData.FunctionStarts);
168169
}
169170

170171
void MappingTraits<MachOYAML::RebaseOpcode>::mapping(
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
--- !mach-o
2+
FileHeader:
3+
magic: 0xFEEDFACF
4+
cputype: 0x100000C
5+
cpusubtype: 0x0
6+
filetype: 0x2
7+
ncmds: 15
8+
sizeofcmds: 728
9+
flags: 0x200085
10+
reserved: 0x0
11+
LoadCommands:
12+
- cmd: LC_SEGMENT_64
13+
cmdsize: 72
14+
segname: __PAGEZERO
15+
vmaddr: 0
16+
vmsize: 4294967296
17+
fileoff: 0
18+
filesize: 0
19+
maxprot: 0
20+
initprot: 0
21+
nsects: 0
22+
flags: 0
23+
- cmd: LC_SEGMENT_64
24+
cmdsize: 232
25+
segname: __TEXT
26+
vmaddr: 4294967296
27+
vmsize: 16384
28+
fileoff: 0
29+
filesize: 16384
30+
maxprot: 5
31+
initprot: 5
32+
nsects: 2
33+
flags: 0
34+
Sections:
35+
- sectname: __text
36+
segname: __TEXT
37+
addr: 0x100003F80
38+
size: 48
39+
offset: 0x3F80
40+
align: 2
41+
reloff: 0x0
42+
nreloc: 0
43+
flags: 0x80000400
44+
reserved1: 0x0
45+
reserved2: 0x0
46+
reserved3: 0x0
47+
content: C0035FD6FF8300D1FD7B01A9FD43009108008052E80B00B9BFC31FB8F9FFFF97E00B40B9FD7B41A9FF830091C0035FD6
48+
- sectname: __unwind_info
49+
segname: __TEXT
50+
addr: 0x100003FB0
51+
size: 80
52+
offset: 0x3FB0
53+
align: 2
54+
reloff: 0x0
55+
nreloc: 0
56+
flags: 0x0
57+
reserved1: 0x0
58+
reserved2: 0x0
59+
reserved3: 0x0
60+
content: 010000001C000000000000001C000000000000001C00000002000000803F00003400000034000000B13F00000000000034000000030000000C0002001400020000000001040000000000000400000002
61+
- cmd: LC_SEGMENT_64
62+
cmdsize: 72
63+
segname: __LINKEDIT
64+
vmaddr: 4294983680
65+
vmsize: 16384
66+
fileoff: 16384
67+
filesize: 208
68+
maxprot: 1
69+
initprot: 1
70+
nsects: 0
71+
flags: 0
72+
- cmd: LC_DYLD_CHAINED_FIXUPS
73+
cmdsize: 16
74+
dataoff: 16384
75+
datasize: 56
76+
- cmd: LC_DYLD_EXPORTS_TRIE
77+
cmdsize: 16
78+
dataoff: 16440
79+
datasize: 56
80+
- cmd: LC_SYMTAB
81+
cmdsize: 24
82+
symoff: 16504
83+
nsyms: 3
84+
stroff: 16552
85+
strsize: 40
86+
- cmd: LC_DYSYMTAB
87+
cmdsize: 80
88+
ilocalsym: 0
89+
nlocalsym: 0
90+
iextdefsym: 0
91+
nextdefsym: 3
92+
iundefsym: 3
93+
nundefsym: 0
94+
tocoff: 0
95+
ntoc: 0
96+
modtaboff: 0
97+
nmodtab: 0
98+
extrefsymoff: 0
99+
nextrefsyms: 0
100+
indirectsymoff: 0
101+
nindirectsyms: 0
102+
extreloff: 0
103+
nextrel: 0
104+
locreloff: 0
105+
nlocrel: 0
106+
- cmd: LC_LOAD_DYLINKER
107+
cmdsize: 32
108+
name: 12
109+
Content: '/usr/lib/dyld'
110+
ZeroPadBytes: 7
111+
- cmd: LC_UUID
112+
cmdsize: 24
113+
uuid: E1953271-0EDC-3009-9BED-635C8BB3DFE7
114+
- cmd: LC_BUILD_VERSION
115+
cmdsize: 32
116+
platform: 1
117+
minos: 786432
118+
sdk: 786688
119+
ntools: 1
120+
Tools:
121+
- tool: 3
122+
version: 46596096
123+
- cmd: LC_SOURCE_VERSION
124+
cmdsize: 16
125+
version: 0
126+
- cmd: LC_MAIN
127+
cmdsize: 24
128+
entryoff: 16260
129+
stacksize: 0
130+
- cmd: LC_LOAD_DYLIB
131+
cmdsize: 56
132+
dylib:
133+
name: 24
134+
timestamp: 2
135+
current_version: 85917696
136+
compatibility_version: 65536
137+
Content: '/usr/lib/libSystem.B.dylib'
138+
ZeroPadBytes: 6
139+
- cmd: LC_FUNCTION_STARTS
140+
cmdsize: 16
141+
dataoff: 16496
142+
datasize: 8
143+
- cmd: LC_DATA_IN_CODE
144+
cmdsize: 16
145+
dataoff: 16504
146+
datasize: 0
147+
LinkEditData:
148+
NameList:
149+
- n_strx: 2
150+
n_type: 0xF
151+
n_sect: 1
152+
n_desc: 16
153+
n_value: 4294967296
154+
- n_strx: 22
155+
n_type: 0xF
156+
n_sect: 1
157+
n_desc: 0
158+
n_value: 4294983552
159+
- n_strx: 27
160+
n_type: 0xF
161+
n_sect: 1
162+
n_desc: 0
163+
n_value: 4294983556
164+
StringTable:
165+
- ' '
166+
- __mh_execute_header
167+
- _foo
168+
- _main
169+
- ''
170+
- ''
171+
- ''
172+
- ''
173+
- ''
174+
- ''
175+
- ''
176+
FunctionStarts: [ 0x3F80, 0x3F84 ]
177+
...
178+
179+
# RUN: yaml2obj %s -o=%t
180+
# RUN obj2yaml %t | FileCheck %s
181+
# CHECK: FunctionStarts: [ 0x3F80, 0x3F84 ]
182+
183+
# RUN: llvm-objdump --macho --function-starts %t | FileCheck %s --check-prefix=OBJDUMP-VERIFY
184+
# OBJDUMP-VERIFY: function_starts.yaml.tmp:
185+
# OBJDUMP-VERIFY: 0000000100003f80
186+
# OBJDUMP-VERIFY: 0000000100003f84

llvm/tools/obj2yaml/macho2yaml.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class MachODumper {
3434
Error dumpLoadCommands(std::unique_ptr<MachOYAML::Object> &Y);
3535
void dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y);
3636
void dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y);
37+
void dumpFunctionStarts(std::unique_ptr<MachOYAML::Object> &Y);
3738
void dumpBindOpcodes(std::vector<MachOYAML::BindOpcode> &BindOpcodes,
3839
ArrayRef<uint8_t> OpcodeBuffer, bool Lazy = false);
3940
void dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y);
@@ -353,6 +354,15 @@ void MachODumper::dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y) {
353354
dumpExportTrie(Y);
354355
dumpSymbols(Y);
355356
dumpIndirectSymbols(Y);
357+
dumpFunctionStarts(Y);
358+
}
359+
360+
void MachODumper::dumpFunctionStarts(std::unique_ptr<MachOYAML::Object> &Y) {
361+
MachOYAML::LinkEditData &LEData = Y->LinkEdit;
362+
363+
auto FunctionStarts = Obj.getFunctionStarts();
364+
for (auto Addr : FunctionStarts)
365+
LEData.FunctionStarts.push_back(Addr);
356366
}
357367

358368
void MachODumper::dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y) {

0 commit comments

Comments
 (0)