2020-04-22 04:37:57 +08:00
|
|
|
//===- SyntheticSections.h -------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLD_MACHO_SYNTHETIC_SECTIONS_H
|
|
|
|
#define LLD_MACHO_SYNTHETIC_SECTIONS_H
|
|
|
|
|
|
|
|
#include "InputSection.h"
|
|
|
|
#include "Target.h"
|
|
|
|
#include "llvm/ADT/SetVector.h"
|
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
using namespace llvm::MachO;
|
|
|
|
|
2020-04-22 04:37:57 +08:00
|
|
|
namespace lld {
|
|
|
|
namespace macho {
|
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
namespace section_names {
|
|
|
|
|
|
|
|
constexpr const char *pageZero = "__pagezero";
|
|
|
|
constexpr const char *header = "__mach_header";
|
|
|
|
constexpr const char *binding = "__binding";
|
[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
|
|
|
constexpr const char *symbolTable = "__symbol_table";
|
|
|
|
constexpr const char *stringTable = "__string_table";
|
2020-04-28 03:50:59 +08:00
|
|
|
|
|
|
|
} // namespace section_names
|
|
|
|
|
2020-04-22 04:37:57 +08:00
|
|
|
class DylibSymbol;
|
2020-04-28 03:50:59 +08:00
|
|
|
class LoadCommand;
|
|
|
|
|
|
|
|
// The header of the Mach-O file, which must have a file offset of zero.
|
|
|
|
class MachHeaderSection : public InputSection {
|
|
|
|
public:
|
|
|
|
MachHeaderSection();
|
|
|
|
void addLoadCommand(LoadCommand *);
|
|
|
|
bool isHidden() const override { return true; }
|
|
|
|
size_t getSize() const override;
|
|
|
|
void writeTo(uint8_t *buf) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<LoadCommand *> loadCommands;
|
|
|
|
uint32_t sizeOfCmds = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
// A hidden section that exists solely for the purpose of creating the
|
|
|
|
// __PAGEZERO segment, which is used to catch null pointer dereferences.
|
|
|
|
class PageZeroSection : public InputSection {
|
|
|
|
public:
|
|
|
|
PageZeroSection();
|
|
|
|
bool isHidden() const override { return true; }
|
|
|
|
size_t getSize() const override { return ImageBase; }
|
|
|
|
uint64_t getFileSize() const override { return 0; }
|
|
|
|
};
|
2020-04-22 04:37:57 +08:00
|
|
|
|
|
|
|
// This section will be populated by dyld with addresses to non-lazily-loaded
|
|
|
|
// dylib symbols.
|
|
|
|
class GotSection : public InputSection {
|
|
|
|
public:
|
|
|
|
GotSection();
|
|
|
|
|
|
|
|
void addEntry(DylibSymbol &sym);
|
|
|
|
const llvm::SetVector<const DylibSymbol *> &getEntries() const {
|
|
|
|
return entries;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t getSize() const override { return entries.size() * WordSize; }
|
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
bool isNeeded() const override { return !entries.empty(); }
|
|
|
|
|
2020-04-22 04:37:57 +08:00
|
|
|
void writeTo(uint8_t *buf) override {
|
|
|
|
// Nothing to write, GOT contains all zeros at link time; it's populated at
|
|
|
|
// runtime by dyld.
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
llvm::SetVector<const DylibSymbol *> entries;
|
|
|
|
};
|
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
// Stores bind opcodes for telling dyld which symbols to load non-lazily.
|
|
|
|
class BindingSection : public InputSection {
|
|
|
|
public:
|
|
|
|
BindingSection();
|
|
|
|
void finalizeContents();
|
|
|
|
size_t getSize() const override { return contents.size(); }
|
|
|
|
// Like other sections in __LINKEDIT, the binding section is special: its
|
|
|
|
// offsets are recorded in the LC_DYLD_INFO_ONLY load command, instead of in
|
|
|
|
// section headers.
|
|
|
|
bool isHidden() const override { return true; }
|
|
|
|
bool isNeeded() const override;
|
|
|
|
void writeTo(uint8_t *buf) override;
|
|
|
|
|
|
|
|
SmallVector<char, 128> contents;
|
|
|
|
};
|
|
|
|
|
[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
|
|
|
// Stores the strings referenced by the symbol table.
|
|
|
|
class StringTableSection : public InputSection {
|
|
|
|
public:
|
|
|
|
StringTableSection();
|
|
|
|
// Returns the start offset of the added string.
|
|
|
|
uint32_t addString(StringRef);
|
|
|
|
size_t getSize() const override { return size; }
|
|
|
|
// Like other sections in __LINKEDIT, the string table section is special: its
|
|
|
|
// offsets are recorded in the LC_SYMTAB load command, instead of in section
|
|
|
|
// headers.
|
|
|
|
bool isHidden() const override { return true; }
|
|
|
|
void writeTo(uint8_t *buf) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// An n_strx value of 0 always indicates the empty string, so we must locate
|
|
|
|
// our non-empty string values at positive offsets in the string table.
|
|
|
|
// Therefore we insert a dummy value at position zero.
|
|
|
|
std::vector<StringRef> strings{"\0"};
|
|
|
|
size_t size = 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SymtabEntry {
|
|
|
|
Symbol *sym;
|
|
|
|
size_t strx;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SymtabSection : public InputSection {
|
|
|
|
public:
|
|
|
|
SymtabSection(StringTableSection &);
|
|
|
|
void finalizeContents();
|
|
|
|
size_t getNumSymbols() const { return symbols.size(); }
|
|
|
|
size_t getSize() const override;
|
|
|
|
// Like other sections in __LINKEDIT, the symtab section is special: its
|
|
|
|
// offsets are recorded in the LC_SYMTAB load command, instead of in section
|
|
|
|
// headers.
|
|
|
|
bool isHidden() const override { return true; }
|
|
|
|
void writeTo(uint8_t *buf) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
StringTableSection &stringTableSection;
|
|
|
|
std::vector<SymtabEntry> symbols;
|
|
|
|
};
|
|
|
|
|
2020-04-22 04:37:57 +08:00
|
|
|
struct InStruct {
|
2020-04-28 03:50:59 +08:00
|
|
|
GotSection *got = nullptr;
|
2020-04-22 04:37:57 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
extern InStruct in;
|
|
|
|
|
|
|
|
} // namespace macho
|
|
|
|
} // namespace lld
|
|
|
|
|
|
|
|
#endif
|