diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index b38ffeacf27c6e..dcfdac643370bc 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -612,6 +612,34 @@ void ExportSection::finalizeContents() { void ExportSection::writeTo(uint8_t *buf) const { trieBuilder.writeTo(buf); } +FunctionStartsSection::FunctionStartsSection() + : LinkEditSection(segment_names::linkEdit, section_names::functionStarts_) { +} + +void FunctionStartsSection::finalizeContents() { + raw_svector_ostream os{contents}; + uint64_t addr = in.header->addr; + for (const Symbol *sym : symtab->getSymbols()) { + if (const auto *defined = dyn_cast(sym)) { + if (!defined->isec || !isCodeSection(defined->isec)) + continue; + // TODO: Add support for thumbs, in that case + // the lowest bit of nextAddr needs to be set to 1. + uint64_t nextAddr = defined->getVA(); + uint64_t delta = nextAddr - addr; + if (delta == 0) + continue; + encodeULEB128(delta, os); + addr = nextAddr; + } + } + os << '\0'; +} + +void FunctionStartsSection::writeTo(uint8_t *buf) const { + memcpy(buf, contents.data(), contents.size()); +} + SymtabSection::SymtabSection(StringTableSection &stringTableSection) : LinkEditSection(segment_names::linkEdit, section_names::symbolTable), stringTableSection(stringTableSection) {} diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h index aff5a08cab9362..232035f8f5f35f 100644 --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -38,6 +38,7 @@ constexpr const char binding[] = "__binding"; constexpr const char weakBinding[] = "__weak_binding"; constexpr const char lazyBinding[] = "__lazy_binding"; constexpr const char export_[] = "__export"; +constexpr const char functionStarts_[] = "__functionStarts"; constexpr const char symbolTable[] = "__symbol_table"; constexpr const char indirectSymbolTable[] = "__ind_sym_tab"; constexpr const char stringTable[] = "__string_table"; @@ -397,6 +398,17 @@ class ExportSection : public LinkEditSection { size_t size = 0; }; +class FunctionStartsSection : public LinkEditSection { +public: + FunctionStartsSection(); + void finalizeContents(); + uint64_t getRawSize() const override { return contents.size(); } + void writeTo(uint8_t *buf) const override; + +private: + SmallVector contents; +}; + // Stores the strings referenced by the symbol table. class StringTableSection : public LinkEditSection { public: @@ -517,6 +529,7 @@ struct InStruct { WeakBindingSection *weakBinding = nullptr; LazyBindingSection *lazyBinding = nullptr; ExportSection *exports = nullptr; + FunctionStartsSection *functionStarts = nullptr; GotSection *got = nullptr; TlvPointerSection *tlvPointers = nullptr; LazyPointerSection *lazyPointers = nullptr; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index 2d6a41bc5d5521..110c296a36770e 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -114,6 +114,25 @@ class LCDyldInfo : public LoadCommand { ExportSection *exportSection; }; +class LCFunctionStarts : public LoadCommand { +public: + explicit LCFunctionStarts(FunctionStartsSection *functionStarts) + : functionStarts(functionStarts) {} + + uint32_t getSize() const override { return sizeof(linkedit_data_command); } + + void writeTo(uint8_t *buf) const override { + auto *c = reinterpret_cast(buf); + c->cmd = LC_FUNCTION_STARTS; + c->cmdsize = getSize(); + c->dataoff = functionStarts->fileOff; + c->datasize = functionStarts->getFileSize(); + } + +private: + FunctionStartsSection *functionStarts; +}; + class LCDysymtab : public LoadCommand { public: LCDysymtab(SymtabSection *symtabSection, @@ -503,6 +522,7 @@ void Writer::createLoadCommands() { in.header->addLoadCommand(make(symtabSection, stringTableSection)); in.header->addLoadCommand( make(symtabSection, indirectSymtabSection)); + in.header->addLoadCommand(make(in.functionStarts)); for (StringRef path : config->runtimePaths) in.header->addLoadCommand(make(path)); @@ -858,6 +878,7 @@ void Writer::run() { in.weakBinding->finalizeContents(); in.lazyBinding->finalizeContents(); in.exports->finalizeContents(); + in.functionStarts->finalizeContents(); symtabSection->finalizeContents(); indirectSymtabSection->finalizeContents(); @@ -886,6 +907,7 @@ void macho::createSyntheticSections() { in.weakBinding = make(); in.lazyBinding = make(); in.exports = make(); + in.functionStarts = make(); in.got = make(); in.tlvPointers = make(); in.lazyPointers = make(); diff --git a/lld/test/MachO/function-starts.s b/lld/test/MachO/function-starts.s new file mode 100644 index 00000000000000..5bfbaf34de62df --- /dev/null +++ b/lld/test/MachO/function-starts.s @@ -0,0 +1,47 @@ +# REQUIRES: x86 + +# RUN: split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/basic.s -o %t.basic.o +# RUN: %lld %t.basic.o -o %t.basic +# RUN: llvm-objdump --syms --macho --function-starts %t.basic | FileCheck %s --check-prefix=BASIC + +# BASIC: [[#%,MAIN:]] +# BASIC: [[#%,F1:]] +# BASIC: [[#%,F2:]] +# BASIC: SYMBOL TABLE: +# BASIC: [[#MAIN]] {{.*}} _main +# BASIC: [[#F1]] {{.*}} _f1 +# BASIC: [[#F2]] {{.*}} _f2 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/alias.s -o %t.alias.o +# RUN: %lld %t.alias.o -o %t.alias +# RUN: llvm-objdump --syms --macho --function-starts %t.alias | FileCheck %s --check-prefix=ALIAS + +# ALIAS: [[#%,MAIN:]] +# ALIAS: [[#%,F1:]] +# ALIAS: SYMBOL TABLE: +# ALIAS: [[#MAIN]] {{.*}} _main +# ALIAS: [[#F1]] {{.*}} _f1 + +#--- basic.s +.section __TEXT,__text,regular,pure_instructions +.globl _f1 +.globl _f2 +.globl _main +_f1: + retq +_f2: + retq +_main: + retq + +#--- alias.s +.section __TEXT,__text,regular,pure_instructions +.globl _f1 +.equiv _f2, _f1 +.globl _main +_f1: + retq +_main: + retq diff --git a/lld/test/MachO/headerpad.s b/lld/test/MachO/headerpad.s index 750919438cb071..3f7f201ba7d8e4 100644 --- a/lld/test/MachO/headerpad.s +++ b/lld/test/MachO/headerpad.s @@ -72,7 +72,7 @@ # PADMAX-NEXT: segname __TEXT # PADMAX-NEXT: addr # PADMAX-NEXT: size -# PADMAX-NEXT: offset [[#%u, CMDSIZE + 0x20 + mul(0x400, N - 7)]] +# PADMAX-NEXT: offset [[#%u, CMDSIZE + 0x20 + mul(0x400, N - 8)]] ################ All 3 kinds of LCDylib swamped by a larger override # RUN: %lld -o %t/libnull.dylib %t/null.o -dylib \ diff --git a/lld/test/MachO/local-got.s b/lld/test/MachO/local-got.s index e4a1c5e9b97959..9e48c7ec600b0b 100644 --- a/lld/test/MachO/local-got.s +++ b/lld/test/MachO/local-got.s @@ -12,12 +12,12 @@ ## address offset and the contents at that address very similarly, so am using ## --match-full-lines to make sure we match on the right thing. # CHECK: Contents of section __TEXT,__cstring: -# CHECK-NEXT: 100000424 {{.*}} +# CHECK-NEXT: 100000434 {{.*}} ## 1st 8 bytes refer to the start of __cstring + 0xe, 2nd 8 bytes refer to the ## start of __cstring # CHECK: Contents of section __DATA_CONST,__got: -# CHECK-NEXT: [[#%X,ADDR:]] 32040000 01000000 24040000 01000000 {{.*}} +# CHECK-NEXT: [[#%X,ADDR:]] 42040000 01000000 34040000 01000000 {{.*}} # CHECK-NEXT: [[#ADDR + 16]] 00000000 00000000 {{.*}} ## Check that the rebase table is empty. diff --git a/lld/test/MachO/x86-64-relocs.s b/lld/test/MachO/x86-64-relocs.s index c5627c49583fad..8e947445400115 100644 --- a/lld/test/MachO/x86-64-relocs.s +++ b/lld/test/MachO/x86-64-relocs.s @@ -21,7 +21,7 @@ # RUN: llvm-objdump --section=__const --full-contents %t | FileCheck %s --check-prefix=NONPCREL # NONPCREL: Contents of section __DATA,__const: -# NONPCREL-NEXT: 100001000 08040000 01000000 08040000 01000000 +# NONPCREL-NEXT: 100001000 18040000 01000000 18040000 01000000 .section __TEXT,__text .globl _main, _f