2015-08-14 22:12:54 +08:00
|
|
|
//===- Writer.h -------------------------------------------------*- C++ -*-===//
|
2015-05-29 03:09:30 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2015-05-29 03:09:30 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLD_COFF_WRITER_H
|
|
|
|
#define LLD_COFF_WRITER_H
|
|
|
|
|
2017-01-14 11:14:46 +08:00
|
|
|
#include "Chunks.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Object/COFF.h"
|
2018-01-18 03:16:26 +08:00
|
|
|
#include <chrono>
|
2017-01-14 11:14:46 +08:00
|
|
|
#include <cstdint>
|
2015-05-29 03:09:30 +08:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace lld {
|
|
|
|
namespace coff {
|
2017-01-14 11:14:46 +08:00
|
|
|
static const int pageSize = 4096;
|
|
|
|
|
2017-08-29 05:51:07 +08:00
|
|
|
void writeResult();
|
2015-05-29 03:09:30 +08:00
|
|
|
|
2019-03-30 04:25:34 +08:00
|
|
|
class PartialSection {
|
|
|
|
public:
|
|
|
|
PartialSection(StringRef n, uint32_t chars)
|
|
|
|
: name(n), characteristics(chars) {}
|
|
|
|
StringRef name;
|
|
|
|
unsigned characteristics;
|
|
|
|
std::vector<Chunk *> chunks;
|
|
|
|
};
|
|
|
|
|
2017-01-14 11:14:46 +08:00
|
|
|
// OutputSection represents a section in an output file. It's a
|
|
|
|
// container of chunks. OutputSection and Chunk are 1:N relationship.
|
|
|
|
// Chunks cannot belong to more than one OutputSections. The writer
|
|
|
|
// creates multiple OutputSections and assign them unique,
|
|
|
|
// non-overlapping file offsets and RVAs.
|
|
|
|
class OutputSection {
|
|
|
|
public:
|
2018-04-21 05:10:33 +08:00
|
|
|
OutputSection(llvm::StringRef n, uint32_t chars) : name(n) {
|
|
|
|
header.Characteristics = chars;
|
|
|
|
}
|
2017-01-14 11:14:46 +08:00
|
|
|
void addChunk(Chunk *c);
|
[COFF] Provide __CTOR_LIST__ and __DTOR_LIST__ symbols for MinGW
MinGW uses these kind of list terminator symbols for traversing
the constructor/destructor lists. These list terminators are
actual pointers entries in the lists, with the values 0 and
(uintptr_t)-1 (instead of just symbols pointing to the start/end
of the list).
(This mechanism exists in both the mingw-w64 crt startup code and
in libgcc; normally the mingw-w64 one is used, but a DLL build of
libgcc uses the libgcc one. Therefore it's not trivial to change
the mechanism without lots of cross-project synchronization and
potentially invalidating some combinations of old/new versions
of them.)
When mingw-w64 has been used with lld so far, the CRT startup object
files have so far provided these symbols, ending up with different,
incompatible builds of the CRT startup object files depending on
whether binutils or lld are going to be used.
In order to avoid the need of different configuration of the CRT startup
object files depending on what linker to be used, provide these symbols
in lld instead. (Mingw-w64 checks at build time whether the linker
provides these symbols or not.) This unifies this particular detail
between the two linkers.
This does disallow the use of the very latest lld with older versions
of mingw-w64 (the configure check for the list was added recently;
earlier it simply checked whether the CRT was built with gcc or clang),
and requires rebuilding the mingw-w64 CRT. But the number of users of
lld+mingw still is low enough that such a change should be tolerable,
and unifies this aspect of the toolchains, easing interoperability
between the toolchains for the future.
The actual test for this feature is added in ctors_dtors_priority.s,
but a number of other tests that checked absolute output addresses
are updated.
Differential Revision: https://reviews.llvm.org/D52053
llvm-svn: 342294
2018-09-15 06:26:59 +08:00
|
|
|
void insertChunkAtStart(Chunk *c);
|
2018-04-21 05:10:33 +08:00
|
|
|
void merge(OutputSection *other);
|
2017-01-14 11:14:46 +08:00
|
|
|
void setPermissions(uint32_t c);
|
|
|
|
uint64_t getRVA() { return header.VirtualAddress; }
|
|
|
|
uint64_t getFileOff() { return header.PointerToRawData; }
|
|
|
|
void writeHeaderTo(uint8_t *buf);
|
2019-03-30 04:25:34 +08:00
|
|
|
void addContributingPartialSection(PartialSection *sec);
|
2017-01-14 11:14:46 +08:00
|
|
|
|
|
|
|
// Returns the size of this section in an executable memory image.
|
|
|
|
// This may be smaller than the raw size (the raw size is multiple
|
|
|
|
// of disk sector size, so there may be padding at end), or may be
|
|
|
|
// larger (if that's the case, the loader reserves spaces after end
|
|
|
|
// of raw data).
|
|
|
|
uint64_t getVirtualSize() { return header.VirtualSize; }
|
|
|
|
|
|
|
|
// Returns the size of the section in the output file.
|
|
|
|
uint64_t getRawSize() { return header.SizeOfRawData; }
|
|
|
|
|
|
|
|
// Set offset into the string table storing this section name.
|
|
|
|
// Used only when the name is longer than 8 bytes.
|
|
|
|
void setStringTableOff(uint32_t v) { stringTableOff = v; }
|
|
|
|
|
|
|
|
// N.B. The section index is one based.
|
|
|
|
uint32_t sectionIndex = 0;
|
|
|
|
|
|
|
|
llvm::StringRef name;
|
2018-04-21 05:10:33 +08:00
|
|
|
llvm::object::coff_section header = {};
|
2018-03-16 05:13:46 +08:00
|
|
|
|
2018-09-25 18:59:29 +08:00
|
|
|
std::vector<Chunk *> chunks;
|
|
|
|
std::vector<Chunk *> origChunks;
|
|
|
|
|
2019-03-30 04:25:34 +08:00
|
|
|
std::vector<PartialSection *> contribSections;
|
|
|
|
|
2018-03-16 05:13:46 +08:00
|
|
|
private:
|
2017-01-14 11:14:46 +08:00
|
|
|
uint32_t stringTableOff = 0;
|
|
|
|
};
|
|
|
|
|
2019-03-30 04:25:34 +08:00
|
|
|
} // namespace coff
|
|
|
|
} // namespace lld
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
#endif
|