forked from OSchip/llvm-project
[lld][MachO] Add support for LC_FUNCTION_STARTS
Add first bits for emitting LC_FUNCTION_STARTS. Test plan: make check-all Differential revision: https://reviews.llvm.org/D97260
This commit is contained in:
parent
7a3e664db5
commit
f344dfebdb
|
@ -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<Defined>(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) {}
|
||||
|
|
|
@ -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 @@ private:
|
|||
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<char, 128> 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;
|
||||
|
|
|
@ -114,6 +114,25 @@ public:
|
|||
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<linkedit_data_command *>(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<LCSymtab>(symtabSection, stringTableSection));
|
||||
in.header->addLoadCommand(
|
||||
make<LCDysymtab>(symtabSection, indirectSymtabSection));
|
||||
in.header->addLoadCommand(make<LCFunctionStarts>(in.functionStarts));
|
||||
for (StringRef path : config->runtimePaths)
|
||||
in.header->addLoadCommand(make<LCRPath>(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<WeakBindingSection>();
|
||||
in.lazyBinding = make<LazyBindingSection>();
|
||||
in.exports = make<ExportSection>();
|
||||
in.functionStarts = make<FunctionStartsSection>();
|
||||
in.got = make<GotSection>();
|
||||
in.tlvPointers = make<TlvPointerSection>();
|
||||
in.lazyPointers = make<LazyPointerSection>();
|
||||
|
|
|
@ -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
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue