2020-04-22 04:37:57 +08:00
|
|
|
//===- SyntheticSections.cpp ---------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "SyntheticSections.h"
|
2020-04-29 07:58:22 +08:00
|
|
|
#include "Config.h"
|
2020-04-30 06:42:19 +08:00
|
|
|
#include "ExportTrie.h"
|
2020-04-28 03:50:59 +08:00
|
|
|
#include "InputFiles.h"
|
|
|
|
#include "OutputSegment.h"
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
#include "SymbolTable.h"
|
2020-04-22 04:37:57 +08:00
|
|
|
#include "Symbols.h"
|
2020-04-28 03:50:59 +08:00
|
|
|
#include "Writer.h"
|
2020-04-22 04:37:57 +08:00
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
#include "lld/Common/ErrorHandler.h"
|
|
|
|
#include "llvm/Support/EndianStream.h"
|
|
|
|
#include "llvm/Support/LEB128.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
2020-04-22 04:37:57 +08:00
|
|
|
using namespace llvm::MachO;
|
2020-04-28 03:50:59 +08:00
|
|
|
using namespace llvm::support;
|
[lld-macho] Support calls to functions in dylibs
Summary:
This diff implements lazy symbol binding -- very similar to the PLT
mechanism in ELF.
ELF's .plt section is broken up into two sections in Mach-O:
StubsSection and StubHelperSection. Calls to functions in dylibs will
end up calling into StubsSection, which contains indirect jumps to
addresses stored in the LazyPointerSection (the counterpart to ELF's
.plt.got).
Initially, the LazyPointerSection contains addresses that point into one
of the entry points in the middle of the StubHelperSection. The code in
StubHelperSection will push on the stack an offset into the
LazyBindingSection. The push is followed by a jump to the beginning of
the StubHelperSection (similar to PLT0), which then calls into
dyld_stub_binder. dyld_stub_binder is a non-lazily bound symbol, so this
call looks it up in the GOT.
The stub binder will look up the bind opcodes in the LazyBindingSection
at the given offset. The bind opcodes will tell the binder to update the
address in the LazyPointerSection to point to the symbol, so that
subsequent calls don't have to redo the symbol resolution. The binder
will then jump to the resolved symbol.
Depends on D78269.
Reviewers: ruiu, pcc, MaskRay, smeenai, alexshap, gkm, Ktwu, christylee
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D78270
2020-05-06 08:38:10 +08:00
|
|
|
using namespace llvm::support::endian;
|
2020-04-22 04:37:57 +08:00
|
|
|
|
|
|
|
namespace lld {
|
|
|
|
namespace macho {
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
SyntheticSection::SyntheticSection(const char *segname, const char *name)
|
2020-05-06 07:37:34 +08:00
|
|
|
: OutputSection(SyntheticKind, name) {
|
2020-05-02 07:29:06 +08:00
|
|
|
// Synthetic sections always know which segment they belong to so hook
|
|
|
|
// them up when they're made
|
|
|
|
getOrCreateOutputSegment(segname)->addOutputSection(this);
|
2020-04-28 03:50:59 +08:00
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
// dyld3's MachOLoaded::getSlide() assumes that the __TEXT segment starts
|
|
|
|
// from the beginning of the file (i.e. the header).
|
|
|
|
MachHeaderSection::MachHeaderSection()
|
|
|
|
: SyntheticSection(segment_names::text, section_names::header) {}
|
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
void MachHeaderSection::addLoadCommand(LoadCommand *lc) {
|
|
|
|
loadCommands.push_back(lc);
|
|
|
|
sizeOfCmds += lc->getSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t MachHeaderSection::getSize() const {
|
|
|
|
return sizeof(mach_header_64) + sizeOfCmds;
|
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
void MachHeaderSection::writeTo(uint8_t *buf) const {
|
2020-04-28 03:50:59 +08:00
|
|
|
auto *hdr = reinterpret_cast<mach_header_64 *>(buf);
|
|
|
|
hdr->magic = MH_MAGIC_64;
|
|
|
|
hdr->cputype = CPU_TYPE_X86_64;
|
|
|
|
hdr->cpusubtype = CPU_SUBTYPE_X86_64_ALL | CPU_SUBTYPE_LIB64;
|
2020-04-29 07:58:22 +08:00
|
|
|
hdr->filetype = config->outputType;
|
2020-04-28 03:50:59 +08:00
|
|
|
hdr->ncmds = loadCommands.size();
|
|
|
|
hdr->sizeofcmds = sizeOfCmds;
|
|
|
|
hdr->flags = MH_NOUNDEFS | MH_DYLDLINK | MH_TWOLEVEL;
|
2020-04-24 11:16:49 +08:00
|
|
|
if (config->outputType == MH_DYLIB && !config->hasReexports)
|
[lld-macho] Support calls to functions in dylibs
Summary:
This diff implements lazy symbol binding -- very similar to the PLT
mechanism in ELF.
ELF's .plt section is broken up into two sections in Mach-O:
StubsSection and StubHelperSection. Calls to functions in dylibs will
end up calling into StubsSection, which contains indirect jumps to
addresses stored in the LazyPointerSection (the counterpart to ELF's
.plt.got).
Initially, the LazyPointerSection contains addresses that point into one
of the entry points in the middle of the StubHelperSection. The code in
StubHelperSection will push on the stack an offset into the
LazyBindingSection. The push is followed by a jump to the beginning of
the StubHelperSection (similar to PLT0), which then calls into
dyld_stub_binder. dyld_stub_binder is a non-lazily bound symbol, so this
call looks it up in the GOT.
The stub binder will look up the bind opcodes in the LazyBindingSection
at the given offset. The bind opcodes will tell the binder to update the
address in the LazyPointerSection to point to the symbol, so that
subsequent calls don't have to redo the symbol resolution. The binder
will then jump to the resolved symbol.
Depends on D78269.
Reviewers: ruiu, pcc, MaskRay, smeenai, alexshap, gkm, Ktwu, christylee
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D78270
2020-05-06 08:38:10 +08:00
|
|
|
hdr->flags |= MH_NO_REEXPORTED_DYLIBS;
|
2020-04-28 03:50:59 +08:00
|
|
|
|
|
|
|
uint8_t *p = reinterpret_cast<uint8_t *>(hdr + 1);
|
|
|
|
for (LoadCommand *lc : loadCommands) {
|
|
|
|
lc->writeTo(p);
|
|
|
|
p += lc->getSize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
PageZeroSection::PageZeroSection()
|
|
|
|
: SyntheticSection(segment_names::pageZero, section_names::pageZero) {}
|
2020-04-28 03:50:59 +08:00
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
GotSection::GotSection()
|
|
|
|
: SyntheticSection(segment_names::dataConst, section_names::got) {
|
2020-04-22 04:37:57 +08:00
|
|
|
align = 8;
|
|
|
|
flags = S_NON_LAZY_SYMBOL_POINTERS;
|
|
|
|
|
|
|
|
// TODO: section_64::reserved1 should be an index into the indirect symbol
|
|
|
|
// table, which we do not currently emit
|
|
|
|
}
|
|
|
|
|
|
|
|
void GotSection::addEntry(DylibSymbol &sym) {
|
|
|
|
if (entries.insert(&sym)) {
|
|
|
|
sym.gotIndex = entries.size() - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
BindingSection::BindingSection()
|
|
|
|
: SyntheticSection(segment_names::linkEdit, section_names::binding) {}
|
2020-04-28 03:50:59 +08:00
|
|
|
|
|
|
|
bool BindingSection::isNeeded() const { return in.got->isNeeded(); }
|
|
|
|
|
|
|
|
// Emit bind opcodes, which are a stream of byte-sized opcodes that dyld
|
|
|
|
// interprets to update a record with the following fields:
|
|
|
|
// * segment index (of the segment to write the symbol addresses to, typically
|
|
|
|
// the __DATA_CONST segment which contains the GOT)
|
|
|
|
// * offset within the segment, indicating the next location to write a binding
|
|
|
|
// * symbol type
|
|
|
|
// * symbol library ordinal (the index of its library's LC_LOAD_DYLIB command)
|
|
|
|
// * symbol name
|
|
|
|
// * addend
|
|
|
|
// When dyld sees BIND_OPCODE_DO_BIND, it uses the current record state to bind
|
|
|
|
// a symbol in the GOT, and increments the segment offset to point to the next
|
|
|
|
// entry. It does *not* clear the record state after doing the bind, so
|
|
|
|
// subsequent opcodes only need to encode the differences between bindings.
|
|
|
|
void BindingSection::finalizeContents() {
|
|
|
|
if (!isNeeded())
|
|
|
|
return;
|
|
|
|
|
|
|
|
raw_svector_ostream os{contents};
|
|
|
|
os << static_cast<uint8_t>(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
|
|
|
|
in.got->parent->index);
|
2020-05-02 07:29:06 +08:00
|
|
|
encodeULEB128(in.got->getSegmentOffset(), os);
|
2020-04-28 03:50:59 +08:00
|
|
|
for (const DylibSymbol *sym : in.got->getEntries()) {
|
|
|
|
// TODO: Implement compact encoding -- we only need to encode the
|
|
|
|
// differences between consecutive symbol entries.
|
|
|
|
if (sym->file->ordinal <= BIND_IMMEDIATE_MASK) {
|
|
|
|
os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
|
|
|
|
sym->file->ordinal);
|
|
|
|
} else {
|
|
|
|
error("TODO: Support larger dylib symbol ordinals");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
os << static_cast<uint8_t>(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
|
|
|
|
<< sym->getName() << '\0'
|
|
|
|
<< static_cast<uint8_t>(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER)
|
|
|
|
<< static_cast<uint8_t>(BIND_OPCODE_DO_BIND);
|
|
|
|
}
|
|
|
|
|
|
|
|
os << static_cast<uint8_t>(BIND_OPCODE_DONE);
|
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
void BindingSection::writeTo(uint8_t *buf) const {
|
2020-04-28 03:50:59 +08:00
|
|
|
memcpy(buf, contents.data(), contents.size());
|
|
|
|
}
|
|
|
|
|
[lld-macho] Support calls to functions in dylibs
Summary:
This diff implements lazy symbol binding -- very similar to the PLT
mechanism in ELF.
ELF's .plt section is broken up into two sections in Mach-O:
StubsSection and StubHelperSection. Calls to functions in dylibs will
end up calling into StubsSection, which contains indirect jumps to
addresses stored in the LazyPointerSection (the counterpart to ELF's
.plt.got).
Initially, the LazyPointerSection contains addresses that point into one
of the entry points in the middle of the StubHelperSection. The code in
StubHelperSection will push on the stack an offset into the
LazyBindingSection. The push is followed by a jump to the beginning of
the StubHelperSection (similar to PLT0), which then calls into
dyld_stub_binder. dyld_stub_binder is a non-lazily bound symbol, so this
call looks it up in the GOT.
The stub binder will look up the bind opcodes in the LazyBindingSection
at the given offset. The bind opcodes will tell the binder to update the
address in the LazyPointerSection to point to the symbol, so that
subsequent calls don't have to redo the symbol resolution. The binder
will then jump to the resolved symbol.
Depends on D78269.
Reviewers: ruiu, pcc, MaskRay, smeenai, alexshap, gkm, Ktwu, christylee
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D78270
2020-05-06 08:38:10 +08:00
|
|
|
StubsSection::StubsSection()
|
|
|
|
: SyntheticSection(segment_names::text, "__stubs") {}
|
|
|
|
|
|
|
|
size_t StubsSection::getSize() const {
|
|
|
|
return entries.size() * target->stubSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StubsSection::writeTo(uint8_t *buf) const {
|
|
|
|
size_t off = 0;
|
|
|
|
for (const DylibSymbol *sym : in.stubs->getEntries()) {
|
|
|
|
target->writeStub(buf + off, *sym);
|
|
|
|
off += target->stubSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StubsSection::addEntry(DylibSymbol &sym) {
|
|
|
|
if (entries.insert(&sym))
|
|
|
|
sym.stubsIndex = entries.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
StubHelperSection::StubHelperSection()
|
|
|
|
: SyntheticSection(segment_names::text, "__stub_helper") {}
|
|
|
|
|
|
|
|
size_t StubHelperSection::getSize() const {
|
|
|
|
return target->stubHelperHeaderSize +
|
|
|
|
in.stubs->getEntries().size() * target->stubHelperEntrySize;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StubHelperSection::isNeeded() const {
|
|
|
|
return !in.stubs->getEntries().empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StubHelperSection::writeTo(uint8_t *buf) const {
|
|
|
|
target->writeStubHelperHeader(buf);
|
|
|
|
size_t off = target->stubHelperHeaderSize;
|
|
|
|
for (const DylibSymbol *sym : in.stubs->getEntries()) {
|
|
|
|
target->writeStubHelperEntry(buf + off, *sym, addr + off);
|
|
|
|
off += target->stubHelperEntrySize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StubHelperSection::setup() {
|
|
|
|
stubBinder = dyn_cast_or_null<DylibSymbol>(symtab->find("dyld_stub_binder"));
|
|
|
|
if (stubBinder == nullptr) {
|
|
|
|
error("symbol dyld_stub_binder not found (normally in libSystem.dylib). "
|
|
|
|
"Needed to perform lazy binding.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
in.got->addEntry(*stubBinder);
|
|
|
|
|
|
|
|
inputSections.push_back(in.imageLoaderCache);
|
|
|
|
symtab->addDefined("__dyld_private", in.imageLoaderCache, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImageLoaderCacheSection::ImageLoaderCacheSection() {
|
|
|
|
segname = segment_names::data;
|
|
|
|
name = "__data";
|
|
|
|
}
|
|
|
|
|
|
|
|
LazyPointerSection::LazyPointerSection()
|
|
|
|
: SyntheticSection(segment_names::data, "__la_symbol_ptr") {
|
|
|
|
align = 8;
|
|
|
|
flags = S_LAZY_SYMBOL_POINTERS;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t LazyPointerSection::getSize() const {
|
|
|
|
return in.stubs->getEntries().size() * WordSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool LazyPointerSection::isNeeded() const {
|
|
|
|
return !in.stubs->getEntries().empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LazyPointerSection::writeTo(uint8_t *buf) const {
|
|
|
|
size_t off = 0;
|
|
|
|
for (const DylibSymbol *sym : in.stubs->getEntries()) {
|
|
|
|
uint64_t stubHelperOffset = target->stubHelperHeaderSize +
|
|
|
|
sym->stubsIndex * target->stubHelperEntrySize;
|
|
|
|
write64le(buf + off, in.stubHelper->addr + stubHelperOffset);
|
|
|
|
off += WordSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LazyBindingSection::LazyBindingSection()
|
|
|
|
: SyntheticSection(segment_names::linkEdit, section_names::lazyBinding) {}
|
|
|
|
|
|
|
|
bool LazyBindingSection::isNeeded() const { return in.stubs->isNeeded(); }
|
|
|
|
|
|
|
|
void LazyBindingSection::finalizeContents() {
|
|
|
|
// TODO: Just precompute output size here instead of writing to a temporary
|
|
|
|
// buffer
|
|
|
|
for (DylibSymbol *sym : in.stubs->getEntries())
|
|
|
|
sym->lazyBindOffset = encode(*sym);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LazyBindingSection::writeTo(uint8_t *buf) const {
|
|
|
|
memcpy(buf, contents.data(), contents.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unlike the non-lazy binding section, the bind opcodes in this section aren't
|
|
|
|
// interpreted all at once. Rather, dyld will start interpreting opcodes at a
|
|
|
|
// given offset, typically only binding a single symbol before it finds a
|
|
|
|
// BIND_OPCODE_DONE terminator. As such, unlike in the non-lazy-binding case,
|
|
|
|
// we cannot encode just the differences between symbols; we have to emit the
|
|
|
|
// complete bind information for each symbol.
|
|
|
|
uint32_t LazyBindingSection::encode(const DylibSymbol &sym) {
|
|
|
|
uint32_t opstreamOffset = contents.size();
|
|
|
|
OutputSegment *dataSeg = in.lazyPointers->parent;
|
|
|
|
os << static_cast<uint8_t>(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
|
|
|
|
dataSeg->index);
|
|
|
|
uint64_t offset = in.lazyPointers->addr - dataSeg->firstSection()->addr +
|
|
|
|
sym.stubsIndex * WordSize;
|
|
|
|
encodeULEB128(offset, os);
|
|
|
|
if (sym.file->ordinal <= BIND_IMMEDIATE_MASK)
|
|
|
|
os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
|
|
|
|
sym.file->ordinal);
|
|
|
|
else
|
|
|
|
fatal("TODO: Support larger dylib symbol ordinals");
|
|
|
|
|
|
|
|
os << static_cast<uint8_t>(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
|
|
|
|
<< sym.getName() << '\0' << static_cast<uint8_t>(BIND_OPCODE_DO_BIND)
|
|
|
|
<< static_cast<uint8_t>(BIND_OPCODE_DONE);
|
|
|
|
return opstreamOffset;
|
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
ExportSection::ExportSection()
|
|
|
|
: SyntheticSection(segment_names::linkEdit, section_names::export_) {}
|
2020-04-29 07:58:22 +08:00
|
|
|
|
|
|
|
void ExportSection::finalizeContents() {
|
|
|
|
// TODO: We should check symbol visibility.
|
|
|
|
for (const Symbol *sym : symtab->getSymbols())
|
|
|
|
if (auto *defined = dyn_cast<Defined>(sym))
|
2020-04-30 06:42:19 +08:00
|
|
|
trieBuilder.addSymbol(*defined);
|
|
|
|
size = trieBuilder.build();
|
2020-04-29 07:58:22 +08:00
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
void ExportSection::writeTo(uint8_t *buf) const { trieBuilder.writeTo(buf); }
|
2020-04-29 07:58:22 +08:00
|
|
|
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
SymtabSection::SymtabSection(StringTableSection &stringTableSection)
|
2020-05-02 07:29:06 +08:00
|
|
|
: SyntheticSection(segment_names::linkEdit, section_names::symbolTable),
|
|
|
|
stringTableSection(stringTableSection) {
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
// TODO: When we introduce the SyntheticSections superclass, we should make
|
|
|
|
// all synthetic sections aligned to WordSize by default.
|
|
|
|
align = WordSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t SymtabSection::getSize() const {
|
|
|
|
return symbols.size() * sizeof(nlist_64);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymtabSection::finalizeContents() {
|
2020-04-29 07:58:22 +08:00
|
|
|
// TODO support other symbol types
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
for (Symbol *sym : symtab->getSymbols())
|
2020-04-29 07:58:22 +08:00
|
|
|
if (isa<Defined>(sym))
|
|
|
|
symbols.push_back({sym, stringTableSection.addString(sym->getName())});
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
void SymtabSection::writeTo(uint8_t *buf) const {
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
auto *nList = reinterpret_cast<nlist_64 *>(buf);
|
|
|
|
for (const SymtabEntry &entry : symbols) {
|
2020-04-29 07:58:22 +08:00
|
|
|
nList->n_strx = entry.strx;
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
// TODO support other symbol types
|
|
|
|
// TODO populate n_desc
|
2020-05-12 06:50:22 +08:00
|
|
|
if (auto *defined = dyn_cast<Defined>(entry.sym)) {
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
nList->n_type = N_EXT | N_SECT;
|
2020-05-02 07:29:06 +08:00
|
|
|
nList->n_sect = defined->isec->parent->index;
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
// For the N_SECT symbol type, n_value is the address of the symbol
|
2020-05-02 07:29:06 +08:00
|
|
|
nList->n_value = defined->value + defined->isec->getVA();
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
}
|
|
|
|
++nList;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
StringTableSection::StringTableSection()
|
|
|
|
: SyntheticSection(segment_names::linkEdit, section_names::stringTable) {}
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
|
|
|
|
uint32_t StringTableSection::addString(StringRef str) {
|
|
|
|
uint32_t strx = size;
|
|
|
|
strings.push_back(str);
|
|
|
|
size += str.size() + 1; // account for null terminator
|
|
|
|
return strx;
|
|
|
|
}
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
void StringTableSection::writeTo(uint8_t *buf) const {
|
[lld-macho][reland] Add basic symbol table output
This diff implements basic support for writing a symbol table.
Attributes are loosely supported for extern symbols and not at all for
other types.
Initial version by Kellie Medlin <kelliem@fb.com>
Originally committed in a3d95a50ee33 and reverted in fbae153ca583 due to
UBSAN erroring over unaligned writes. That has been fixed in the
current diff with the following changes:
```
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -133,6 +133,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
: stringTableSection(stringTableSection) {
segname = segment_names::linkEdit;
name = section_names::symbolTable;
+ // TODO: When we introduce the SyntheticSections superclass, we should make
+ // all synthetic sections aligned to WordSize by default.
+ align = WordSize;
}
size_t SymtabSection::getSize() const {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -371,6 +371,7 @@ void Writer::assignAddresses(OutputSegment *seg) {
ArrayRef<InputSection *> sections = p.second;
for (InputSection *isec : sections) {
addr = alignTo(addr, isec->align);
+ // We must align the file offsets too to avoid misaligned writes of
+ // structs.
+ fileOff = alignTo(fileOff, isec->align);
isec->addr = addr;
addr += isec->getSize();
fileOff += isec->getFileSize();
@@ -396,6 +397,7 @@ void Writer::writeSections() {
uint64_t fileOff = seg->fileOff;
for (auto § : seg->getSections()) {
for (InputSection *isec : sect.second) {
+ fileOff = alignTo(fileOff, isec->align);
isec->writeTo(buf + fileOff);
fileOff += isec->getFileSize();
}
```
I don't think it's easy to write a test for alignment (that doesn't
involve brittly hard-coding file offsets), so there isn't one... but
UBSAN builds pass now.
Differential Revision: https://reviews.llvm.org/D79050
2020-04-29 07:58:19 +08:00
|
|
|
uint32_t off = 0;
|
|
|
|
for (StringRef str : strings) {
|
|
|
|
memcpy(buf + off, str.data(), str.size());
|
|
|
|
off += str.size() + 1; // account for null terminator
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-22 04:37:57 +08:00
|
|
|
InStruct in;
|
|
|
|
|
|
|
|
} // namespace macho
|
|
|
|
} // namespace lld
|