[lld] r260188 - Generate LC_FUNCTION_STARTS load command.
Pete Cooper via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 8 17:38:14 PST 2016
Author: pete
Date: Mon Feb 8 19:38:13 2016
New Revision: 260188
URL: http://llvm.org/viewvc/llvm-project?rev=260188&view=rev
Log:
Generate LC_FUNCTION_STARTS load command.
This load command generates data in the LINKEDIT section which
is a list of ULEB128 delta's to all of the functions in the __text section.
It is then 0 terminated and pointer aligned to pad.
ld64 exposes the -function-starts and no-function-starts cmdline options
to override behaviour from the defaults based on file types.
rdar://problem/24472630
Added:
lld/trunk/test/mach-o/function-starts-load-command.yaml
Modified:
lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
lld/trunk/lib/Driver/DarwinLdDriver.cpp
lld/trunk/lib/Driver/DarwinLdOptions.td
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=260188&r1=260187&r2=260188&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Mon Feb 8 19:38:13 2016
@@ -156,6 +156,13 @@ public:
_generateVersionLoadCommand = v;
}
+ bool generateFunctionStartsLoadCommand() const {
+ return _generateFunctionStartsLoadCommand;
+ }
+ void setGenerateFunctionStartsLoadCommand(bool v) {
+ _generateFunctionStartsLoadCommand = v;
+ }
+
uint64_t stackSize() const { return _stackSize; }
void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
@@ -451,6 +458,7 @@ private:
bool _demangle;
bool _mergeObjCCategories = true;
bool _generateVersionLoadCommand = false;
+ bool _generateFunctionStartsLoadCommand = false;
StringRef _bundleLoader;
mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
mutable std::unique_ptr<Writer> _writer;
Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=260188&r1=260187&r2=260188&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Mon Feb 8 19:38:13 2016
@@ -792,6 +792,54 @@ bool DarwinLdDriver::parse(llvm::ArrayRe
}
}
+ // Handle -function_starts or -no_function_starts
+ {
+ bool flagOn = false;
+ bool flagOff = false;
+ if (auto *arg = parsedArgs.getLastArg(OPT_function_starts,
+ OPT_no_function_starts)) {
+ flagOn = arg->getOption().getID() == OPT_function_starts;
+ flagOff = arg->getOption().getID() == OPT_no_function_starts;
+ }
+
+ // default to adding functions start for dynamic code, static code must
+ // opt-in
+ switch (ctx.outputMachOType()) {
+ case llvm::MachO::MH_OBJECT:
+ ctx.setGenerateFunctionStartsLoadCommand(false);
+ break;
+ case llvm::MachO::MH_EXECUTE:
+ // dynamic executables default to generating a version load command,
+ // while static exectuables only generate it if required.
+ if (isStaticExecutable) {
+ if (flagOn)
+ ctx.setGenerateFunctionStartsLoadCommand(true);
+ } else {
+ if (!flagOff)
+ ctx.setGenerateFunctionStartsLoadCommand(true);
+ }
+ break;
+ case llvm::MachO::MH_PRELOAD:
+ case llvm::MachO::MH_KEXT_BUNDLE:
+ if (flagOn)
+ ctx.setGenerateFunctionStartsLoadCommand(true);
+ break;
+ case llvm::MachO::MH_DYLINKER:
+ case llvm::MachO::MH_DYLIB:
+ case llvm::MachO::MH_BUNDLE:
+ if (!flagOff)
+ ctx.setGenerateFunctionStartsLoadCommand(true);
+ break;
+ case llvm::MachO::MH_FVMLIB:
+ case llvm::MachO::MH_DYLDLINK:
+ case llvm::MachO::MH_DYLIB_STUB:
+ case llvm::MachO::MH_DSYM:
+ // We don't generate load commands for these file types, even if
+ // forced on.
+ break;
+ }
+ }
+
// Handle sdk_version
if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_sdk_version)) {
uint32_t sdkVersion = 0;
Modified: lld/trunk/lib/Driver/DarwinLdOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdOptions.td?rev=260188&r1=260187&r2=260188&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdOptions.td (original)
+++ lld/trunk/lib/Driver/DarwinLdOptions.td Mon Feb 8 19:38:13 2016
@@ -43,6 +43,12 @@ def version_load_command : Flag<["-"], "
HelpText<"Force generation of a version load command">, Group<grp_opts>;
def no_version_load_command : Flag<["-"], "no_version_load_command">,
HelpText<"Disable generation of a version load command">, Group<grp_opts>;
+def function_starts : Flag<["-"], "function_starts">,
+ HelpText<"Force generation of a function starts load command">,
+ Group<grp_opts>;
+def no_function_starts : Flag<["-"], "no_function_starts">,
+ HelpText<"Disable generation of a function starts load command">,
+ Group<grp_opts>;
def mllvm : Separate<["-"], "mllvm">,
MetaVarName<"<option>">,
HelpText<"Options to pass to LLVM during LTO">, Group<grp_opts>;
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h?rev=260188&r1=260187&r2=260188&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h Mon Feb 8 19:38:13 2016
@@ -263,6 +263,7 @@ struct NormalizedFile {
std::vector<BindLocation> weakBindingInfo;
std::vector<BindLocation> lazyBindingInfo;
std::vector<Export> exportInfo;
+ std::vector<uint8_t> functionStarts;
std::vector<DataInCode> dataInCode;
// TODO:
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h?rev=260188&r1=260187&r2=260188&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h Mon Feb 8 19:38:13 2016
@@ -18,6 +18,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MachO.h"
#include <system_error>
@@ -25,6 +26,46 @@ namespace lld {
namespace mach_o {
namespace normalized {
+class ByteBuffer {
+public:
+ ByteBuffer() : _ostream(_bytes) { }
+
+ void append_byte(uint8_t b) {
+ _ostream << b;
+ }
+ void append_uleb128(uint64_t value) {
+ llvm::encodeULEB128(value, _ostream);
+ }
+ void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
+ unsigned min = llvm::getULEB128Size(value);
+ assert(min <= byteCount);
+ unsigned pad = byteCount - min;
+ llvm::encodeULEB128(value, _ostream, pad);
+ }
+ void append_sleb128(int64_t value) {
+ llvm::encodeSLEB128(value, _ostream);
+ }
+ void append_string(StringRef str) {
+ _ostream << str;
+ append_byte(0);
+ }
+ void align(unsigned alignment) {
+ while ( (_ostream.tell() % alignment) != 0 )
+ append_byte(0);
+ }
+ size_t size() {
+ return _ostream.tell();
+ }
+ const uint8_t *bytes() {
+ return reinterpret_cast<const uint8_t*>(_ostream.str().data());
+ }
+
+private:
+ SmallVector<char, 128> _bytes;
+ // Stream ivar must be after SmallVector ivar to construct properly.
+ llvm::raw_svector_ostream _ostream;
+};
+
using namespace llvm::support::endian;
using llvm::sys::getSwappedBytes;
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp?rev=260188&r1=260187&r2=260188&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp Mon Feb 8 19:38:13 2016
@@ -37,7 +37,6 @@
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/LEB128.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
@@ -52,46 +51,6 @@ namespace lld {
namespace mach_o {
namespace normalized {
-class ByteBuffer {
-public:
- ByteBuffer() : _ostream(_bytes) { }
-
- void append_byte(uint8_t b) {
- _ostream << b;
- }
- void append_uleb128(uint64_t value) {
- llvm::encodeULEB128(value, _ostream);
- }
- void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
- unsigned min = llvm::getULEB128Size(value);
- assert(min <= byteCount);
- unsigned pad = byteCount - min;
- llvm::encodeULEB128(value, _ostream, pad);
- }
- void append_sleb128(int64_t value) {
- llvm::encodeSLEB128(value, _ostream);
- }
- void append_string(StringRef str) {
- _ostream << str;
- append_byte(0);
- }
- void align(unsigned alignment) {
- while ( (_ostream.tell() % alignment) != 0 )
- append_byte(0);
- }
- size_t size() {
- return _ostream.tell();
- }
- const uint8_t *bytes() {
- return reinterpret_cast<const uint8_t*>(_ostream.str().data());
- }
-
-private:
- SmallVector<char, 128> _bytes;
- // Stream ivar must be after SmallVector ivar to construct properly.
- llvm::raw_svector_ostream _ostream;
-};
-
struct TrieNode; // Forward declaration.
struct TrieEdge : public llvm::ilist_node<TrieEdge> {
@@ -188,6 +147,7 @@ private:
void writeBindingInfo();
void writeLazyBindingInfo();
void writeExportInfo();
+ void writeFunctionStartsInfo();
void writeDataInCodeInfo();
void writeLinkEditContent();
void buildLinkEditInfo();
@@ -195,6 +155,7 @@ private:
void buildBindInfo();
void buildLazyBindInfo();
void buildExportTrie();
+ void computeFunctionStartsSize();
void computeDataInCodeSize();
void computeSymbolTableSizes();
void buildSectionRelocations();
@@ -246,6 +207,7 @@ private:
uint32_t _countOfLoadCommands;
uint32_t _endOfLoadCommands;
uint32_t _startOfRelocations;
+ uint32_t _startOfFunctionStarts;
uint32_t _startOfDataInCode;
uint32_t _startOfSymbols;
uint32_t _startOfIndirectSymbols;
@@ -256,6 +218,7 @@ private:
uint32_t _symbolTableUndefinesStartIndex;
uint32_t _symbolStringPoolSize;
uint32_t _symbolTableSize;
+ uint32_t _functionStartsSize;
uint32_t _dataInCodeSize;
uint32_t _indirectSymbolTableCount;
// Used in object file creation only
@@ -321,6 +284,10 @@ MachOFileLayout::MachOFileLayout(const N
_endOfLoadCommands += sizeof(version_min_command);
_countOfLoadCommands++;
}
+ if (!_file.functionStarts.empty()) {
+ _endOfLoadCommands += sizeof(linkedit_data_command);
+ _countOfLoadCommands++;
+ }
if (!_file.dataInCode.empty()) {
_endOfLoadCommands += sizeof(linkedit_data_command);
_countOfLoadCommands++;
@@ -342,11 +309,13 @@ MachOFileLayout::MachOFileLayout(const N
_endOfSectionsContent = offset;
computeSymbolTableSizes();
+ computeFunctionStartsSize();
computeDataInCodeSize();
// Align start of relocations.
_startOfRelocations = pointerAlign(_endOfSectionsContent);
- _startOfDataInCode = _startOfRelocations + relocCount * 8;
+ _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
+ _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
_startOfSymbols = _startOfDataInCode + _dataInCodeSize;
// Add Indirect symbol table.
_startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
@@ -387,7 +356,8 @@ MachOFileLayout::MachOFileLayout(const N
_endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
_startOfExportTrie = _endOfLazyBindingInfo;
_endOfExportTrie = _startOfExportTrie + _exportTrie.size();
- _startOfDataInCode = _endOfExportTrie;
+ _startOfFunctionStarts = _endOfExportTrie;
+ _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
_startOfSymbols = _startOfDataInCode + _dataInCodeSize;
_startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
_startOfSymbolStrings = _startOfIndirectSymbols
@@ -409,6 +379,7 @@ MachOFileLayout::MachOFileLayout(const N
<< " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
<< " startOfExportTrie=" << _startOfExportTrie << "\n"
<< " endOfExportTrie=" << _endOfExportTrie << "\n"
+ << " startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
<< " startOfDataInCode=" << _startOfDataInCode << "\n"
<< " startOfSymbols=" << _startOfSymbols << "\n"
<< " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
@@ -486,6 +457,12 @@ uint32_t MachOFileLayout::loadCommandsSi
++count;
}
+ // Add LC_FUNCTION_STARTS if needed
+ if (!_file.functionStarts.empty()) {
+ size += sizeof(linkedit_data_command);
+ ++count;
+ }
+
// Add LC_DATA_IN_CODE if needed
if (!_file.dataInCode.empty()) {
size += sizeof(linkedit_data_command);
@@ -821,6 +798,18 @@ std::error_code MachOFileLayout::writeLo
// LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
writeVersionMinLoadCommand(_file, _swap, lc);
+ // Add LC_FUNCTION_STARTS if needed.
+ if (_functionStartsSize != 0) {
+ linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
+ dl->cmd = LC_FUNCTION_STARTS;
+ dl->cmdsize = sizeof(linkedit_data_command);
+ dl->dataoff = _startOfFunctionStarts;
+ dl->datasize = _functionStartsSize;
+ if (_swap)
+ swapStruct(*dl);
+ lc += sizeof(linkedit_data_command);
+ }
+
// Add LC_DATA_IN_CODE if needed.
if (_dataInCodeSize != 0) {
linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
@@ -992,6 +981,18 @@ std::error_code MachOFileLayout::writeLo
lc += size;
}
+ // Add LC_FUNCTION_STARTS if needed.
+ if (_functionStartsSize != 0) {
+ linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
+ dl->cmd = LC_FUNCTION_STARTS;
+ dl->cmdsize = sizeof(linkedit_data_command);
+ dl->dataoff = _startOfFunctionStarts;
+ dl->datasize = _functionStartsSize;
+ if (_swap)
+ swapStruct(*dl);
+ lc += sizeof(linkedit_data_command);
+ }
+
// Add LC_DATA_IN_CODE if needed.
if (_dataInCodeSize != 0) {
linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
@@ -1063,6 +1064,11 @@ void MachOFileLayout::appendSymbols(cons
}
}
+void MachOFileLayout::writeFunctionStartsInfo() {
+ memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
+ _functionStartsSize);
+}
+
void MachOFileLayout::writeDataInCodeInfo() {
uint32_t offset = _startOfDataInCode;
for (const DataInCode &entry : _file.dataInCode) {
@@ -1138,6 +1144,7 @@ void MachOFileLayout::buildLinkEditInfo(
buildLazyBindInfo();
buildExportTrie();
computeSymbolTableSizes();
+ computeFunctionStartsSize();
computeDataInCodeSize();
}
@@ -1417,6 +1424,10 @@ void MachOFileLayout::computeSymbolTable
}
}
+void MachOFileLayout::computeFunctionStartsSize() {
+ _functionStartsSize = _file.functionStarts.size();
+}
+
void MachOFileLayout::computeDataInCodeSize() {
_dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
}
@@ -1424,6 +1435,7 @@ void MachOFileLayout::computeDataInCodeS
void MachOFileLayout::writeLinkEditContent() {
if (_file.fileType == llvm::MachO::MH_OBJECT) {
writeRelocations();
+ writeFunctionStartsInfo();
writeDataInCodeInfo();
writeSymbolTable();
} else {
@@ -1432,6 +1444,7 @@ void MachOFileLayout::writeLinkEditConte
writeLazyBindingInfo();
// TODO: add weak binding info
writeExportInfo();
+ writeFunctionStartsInfo();
writeDataInCodeInfo();
writeSymbolTable();
}
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=260188&r1=260187&r2=260188&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Mon Feb 8 19:38:13 2016
@@ -125,6 +125,7 @@ public:
void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
void addExportInfo(const lld::File &, NormalizedFile &file);
void addSectionRelocs(const lld::File &, NormalizedFile &file);
+ void addFunctionStarts(const lld::File &, NormalizedFile &file);
void buildDataInCodeArray(const lld::File &, NormalizedFile &file);
void addDependentDylibs(const lld::File &, NormalizedFile &file);
void copyEntryPointAddress(NormalizedFile &file);
@@ -1140,6 +1141,50 @@ void Util::addSectionRelocs(const lld::F
}
}
+void Util::addFunctionStarts(const lld::File &, NormalizedFile &file) {
+ if (!_ctx.generateFunctionStartsLoadCommand())
+ return;
+ file.functionStarts.reserve(8192);
+ // Delta compress function starts, starting with the mach header symbol.
+ const uint64_t badAddress = ~0ULL;
+ uint64_t addr = badAddress;
+ for (SectionInfo *si : _sectionInfos) {
+ for (const AtomInfo &info : si->atomsAndOffsets) {
+ auto type = info.atom->contentType();
+ if (type == DefinedAtom::typeMachHeader) {
+ addr = _atomToAddress[info.atom];
+ continue;
+ }
+ if (type != DefinedAtom::typeCode)
+ continue;
+ assert(addr != badAddress && "Missing mach header symbol");
+ // Skip atoms which have 0 size. This is so that LC_FUNCTION_STARTS
+ // can't spill in to the next section.
+ if (!info.atom->size())
+ continue;
+ uint64_t nextAddr = _atomToAddress[info.atom];
+ if (_archHandler.isThumbFunction(*info.atom))
+ nextAddr |= 1;
+ uint64_t delta = nextAddr - addr;
+ if (delta) {
+ ByteBuffer buffer;
+ buffer.append_uleb128(delta);
+ file.functionStarts.insert(file.functionStarts.end(), buffer.bytes(),
+ buffer.bytes() + buffer.size());
+ }
+ addr = nextAddr;
+ }
+ }
+
+ // Null terminate, and pad to pointer size for this arch.
+ file.functionStarts.push_back(0);
+
+ auto size = file.functionStarts.size();
+ for (unsigned i = size, e = llvm::alignTo(size, _ctx.is64Bit() ? 8 : 4);
+ i != e; ++i)
+ file.functionStarts.push_back(0);
+}
+
void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) {
for (SectionInfo *si : _sectionInfos) {
for (const AtomInfo &info : si->atomsAndOffsets) {
@@ -1348,6 +1393,7 @@ normalizedFromAtoms(const lld::File &ato
util.addRebaseAndBindingInfo(atomFile, normFile);
util.addExportInfo(atomFile, normFile);
util.addSectionRelocs(atomFile, normFile);
+ util.addFunctionStarts(atomFile, normFile);
util.buildDataInCodeArray(atomFile, normFile);
util.copyEntryPointAddress(normFile);
Added: lld/trunk/test/mach-o/function-starts-load-command.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/function-starts-load-command.yaml?rev=260188&view=auto
==============================================================================
--- lld/trunk/test/mach-o/function-starts-load-command.yaml (added)
+++ lld/trunk/test/mach-o/function-starts-load-command.yaml Mon Feb 8 19:38:13 2016
@@ -0,0 +1,32 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -function_starts && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -no_function_starts && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -function_starts -no_function_starts && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+# CHECK: Load command {{[0-9]*}}
+# CHECK: cmd LC_FUNCTION_STARTS
+# CHECK: cmdsize 16
+# CHECK: dataoff
+# CHECK: datasize
+
+# NO_FUNCTION_STARTS-NOT: LC_FUNCTION_STARTS
More information about the llvm-commits
mailing list