2020-04-03 02:54:05 +08:00
|
|
|
//===- OutputSegment.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_OUTPUT_SEGMENT_H
|
|
|
|
#define LLD_MACHO_OUTPUT_SEGMENT_H
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
#include "OutputSection.h"
|
2021-07-23 22:12:55 +08:00
|
|
|
#include "Symbols.h"
|
2020-04-03 02:54:05 +08:00
|
|
|
#include "lld/Common/LLVM.h"
|
2021-07-23 22:12:55 +08:00
|
|
|
#include "llvm/ADT/TinyPtrVector.h"
|
2020-04-03 02:54:05 +08:00
|
|
|
|
2021-05-26 02:57:17 +08:00
|
|
|
#include <limits>
|
2021-06-04 00:54:23 +08:00
|
|
|
#include <vector>
|
2021-05-26 02:57:17 +08:00
|
|
|
|
2020-04-03 02:54:05 +08:00
|
|
|
namespace lld {
|
|
|
|
namespace macho {
|
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
namespace segment_names {
|
|
|
|
|
[lld-macho] Refactor segment/section creation, sorting, and merging
Summary:
There were a few issues with the previous setup:
1. The section sorting comparator used a declarative map of section names to
determine the correct order, but it turns out we need to match on more than
just names -- in particular, an upcoming diff will sort based on whether the
S_ZERO_FILL flag is set. This diff changes the sorter to a more imperative but
flexible form.
2. We were sorting OutputSections stored in a MapVector, which left the
MapVector in an inconsistent state -- the wrong keys map to the wrong values!
In practice, we weren't doing key lookups (only container iteration) after the
sort, so this was fine, but it was still a dubious state of affairs. This diff
copies the OutputSections to a vector before sorting them.
3. We were adding unneeded OutputSections to OutputSegments and then filtering
them out later, which meant that we had to remember whether an OutputSegment
was in a pre- or post-filtered state. This diff only adds the sections to the
segments if they are needed.
In addition to those major changes, two minor ones worth noting:
1. I renamed all OutputSection variable names to `osec`, to parallel `isec`.
Previously we were using some inconsistent combination of `osec`, `os`, and
`section`.
2. I added a check (and a test) for InputSections with names that clashed with
those of our synthetic OutputSections.
Reviewers: #lld-macho
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D81887
2020-06-15 15:03:24 +08:00
|
|
|
constexpr const char dataConst[] = "__DATA_CONST";
|
2021-04-28 03:22:44 +08:00
|
|
|
constexpr const char dataDirty[] = "__DATA_DIRTY";
|
|
|
|
constexpr const char data[] = "__DATA";
|
[lld-macho] Emit STABS symbols for debugging, and drop debug sections
Debug sections contain a large amount of data. In order not to bloat the size
of the final binary, we remove them and instead emit STABS symbols for
`dsymutil` and the debugger to locate their contents in the object files.
With this diff, `dsymutil` is able to locate the debug info. However, we need
a few more features before `lldb` is able to work well with our binaries --
e.g. having `LC_DYSYMTAB` accurately reflect the number of local symbols,
emitting `LC_UUID`, and more. Those will be handled in follow-up diffs.
Note also that the STABS we emit differ slightly from what ld64 does. First, we
emit the path to the source file as one `N_SO` symbol instead of two. (`ld64`
emits one `N_SO` for the dirname and one of the basename.) Second, we do not
emit `N_BNSYM` and `N_ENSYM` STABS to mark the start and end of functions,
because the `N_FUN` STABS already serve that purpose. @clayborg recommended
these changes based on his knowledge of what the debugging tools look for.
Additionally, this current implementation doesn't accurately reflect the size
of function symbols. It uses the size of their containing sectioins as a proxy,
but that is only accurate if `.subsections_with_symbols` is set, and if there
isn't an `N_ALT_ENTRY` in that particular subsection. I think we have two
options to solve this:
1. We can split up subsections by symbol even if `.subsections_with_symbols`
is not set, but include constraints to ensure those subsections retain
their order in the final output. This is `ld64`'s approach.
2. We could just add a `size` field to our `Symbol` class. This seems simpler,
and I'm more inclined toward it, but I'm not sure if there are use cases
that it doesn't handle well. As such I'm punting on the decision for now.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D89257
2020-12-02 06:45:01 +08:00
|
|
|
constexpr const char dwarf[] = "__DWARF";
|
2021-04-28 03:22:44 +08:00
|
|
|
constexpr const char import[] = "__IMPORT";
|
|
|
|
constexpr const char ld[] = "__LD"; // output only with -r
|
|
|
|
constexpr const char linkEdit[] = "__LINKEDIT";
|
2021-04-17 04:46:45 +08:00
|
|
|
constexpr const char llvm[] = "__LLVM";
|
2021-04-28 03:22:44 +08:00
|
|
|
constexpr const char pageZero[] = "__PAGEZERO";
|
|
|
|
constexpr const char textExec[] = "__TEXT_EXEC";
|
|
|
|
constexpr const char text[] = "__TEXT";
|
2020-04-28 03:50:59 +08:00
|
|
|
|
|
|
|
} // namespace segment_names
|
|
|
|
|
2020-05-02 07:29:06 +08:00
|
|
|
class OutputSection;
|
2020-04-03 02:54:05 +08:00
|
|
|
class InputSection;
|
|
|
|
|
|
|
|
class OutputSegment {
|
|
|
|
public:
|
2020-05-02 07:29:06 +08:00
|
|
|
void addOutputSection(OutputSection *os);
|
2021-05-26 02:57:18 +08:00
|
|
|
void sortOutputSections();
|
2021-07-23 22:12:55 +08:00
|
|
|
void assignAddressesToStartEndSymbols();
|
2020-04-28 03:50:59 +08:00
|
|
|
|
[lld-macho] Refactor segment/section creation, sorting, and merging
Summary:
There were a few issues with the previous setup:
1. The section sorting comparator used a declarative map of section names to
determine the correct order, but it turns out we need to match on more than
just names -- in particular, an upcoming diff will sort based on whether the
S_ZERO_FILL flag is set. This diff changes the sorter to a more imperative but
flexible form.
2. We were sorting OutputSections stored in a MapVector, which left the
MapVector in an inconsistent state -- the wrong keys map to the wrong values!
In practice, we weren't doing key lookups (only container iteration) after the
sort, so this was fine, but it was still a dubious state of affairs. This diff
copies the OutputSections to a vector before sorting them.
3. We were adding unneeded OutputSections to OutputSegments and then filtering
them out later, which meant that we had to remember whether an OutputSegment
was in a pre- or post-filtered state. This diff only adds the sections to the
segments if they are needed.
In addition to those major changes, two minor ones worth noting:
1. I renamed all OutputSection variable names to `osec`, to parallel `isec`.
Previously we were using some inconsistent combination of `osec`, `os`, and
`section`.
2. I added a check (and a test) for InputSections with names that clashed with
those of our synthetic OutputSections.
Reviewers: #lld-macho
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D81887
2020-06-15 15:03:24 +08:00
|
|
|
const std::vector<OutputSection *> &getSections() const { return sections; }
|
2020-05-02 07:29:06 +08:00
|
|
|
size_t numNonHiddenSections() const;
|
2020-04-28 03:50:59 +08:00
|
|
|
|
|
|
|
uint64_t fileOff = 0;
|
2021-01-07 10:11:44 +08:00
|
|
|
uint64_t fileSize = 0;
|
2021-07-23 22:19:06 +08:00
|
|
|
uint64_t addr = 0;
|
[lld-macho] Ensure segments are laid out contiguously
codesign/libstuff checks that the `__LLVM` segment is directly
before `__LINKEDIT` by checking that `fileOff + fileSize == next segment
fileOff`. Previously, there would be gaps between the segments due to
the fact that their fileOffs are page-aligned but their fileSizes
aren't. In order to satisfy codesign, we page-align fileOff *before*
calculating fileSize. (I don't think codesign checks for the relative
ordering of other segments, so in theory we could do this just for
`__LLVM`, but ld64 seems to do it for all segments.)
Note that we *don't* round up the fileSize of the `__LINKEDIT` segment.
Since it's the last segment, it doesn't need to worry about contiguity;
in addition, codesign checks that the last (hidden) section in
`__LINKEDIT` covers the last byte of the segment, so if we rounded up
`__LINKEDIT`'s size we would have to do the same for its last section,
which is a bother.
While at it, I also addressed a FIXME in the linkedit-contiguity.s test
to cover more `__LINKEDIT` sections.
Reviewed By: #lld-macho, thakis, alexshap
Differential Revision: https://reviews.llvm.org/D100848
2021-04-21 04:58:07 +08:00
|
|
|
uint64_t vmSize = 0;
|
2021-06-21 07:49:13 +08:00
|
|
|
int inputOrder = UnspecifiedInputOrder;
|
2020-04-03 02:54:05 +08:00
|
|
|
StringRef name;
|
2020-04-28 03:50:59 +08:00
|
|
|
uint32_t maxProt = 0;
|
|
|
|
uint32_t initProt = 0;
|
2020-04-22 04:37:57 +08:00
|
|
|
uint8_t index;
|
2020-04-28 03:50:59 +08:00
|
|
|
|
2021-07-23 22:12:55 +08:00
|
|
|
llvm::TinyPtrVector<Defined *> segmentStartSymbols;
|
|
|
|
llvm::TinyPtrVector<Defined *> segmentEndSymbols;
|
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
private:
|
[lld-macho] Refactor segment/section creation, sorting, and merging
Summary:
There were a few issues with the previous setup:
1. The section sorting comparator used a declarative map of section names to
determine the correct order, but it turns out we need to match on more than
just names -- in particular, an upcoming diff will sort based on whether the
S_ZERO_FILL flag is set. This diff changes the sorter to a more imperative but
flexible form.
2. We were sorting OutputSections stored in a MapVector, which left the
MapVector in an inconsistent state -- the wrong keys map to the wrong values!
In practice, we weren't doing key lookups (only container iteration) after the
sort, so this was fine, but it was still a dubious state of affairs. This diff
copies the OutputSections to a vector before sorting them.
3. We were adding unneeded OutputSections to OutputSegments and then filtering
them out later, which meant that we had to remember whether an OutputSegment
was in a pre- or post-filtered state. This diff only adds the sections to the
segments if they are needed.
In addition to those major changes, two minor ones worth noting:
1. I renamed all OutputSection variable names to `osec`, to parallel `isec`.
Previously we were using some inconsistent combination of `osec`, `os`, and
`section`.
2. I added a check (and a test) for InputSections with names that clashed with
those of our synthetic OutputSections.
Reviewers: #lld-macho
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D81887
2020-06-15 15:03:24 +08:00
|
|
|
std::vector<OutputSection *> sections;
|
2020-04-03 02:54:05 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
extern std::vector<OutputSegment *> outputSegments;
|
|
|
|
|
2021-05-26 02:57:18 +08:00
|
|
|
void sortOutputSegments();
|
|
|
|
|
2020-04-28 03:50:59 +08:00
|
|
|
OutputSegment *getOrCreateOutputSegment(StringRef name);
|
2020-04-03 02:54:05 +08:00
|
|
|
|
|
|
|
} // namespace macho
|
|
|
|
} // namespace lld
|
|
|
|
|
|
|
|
#endif
|