Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
HardenedBSD
HardenedBSD
Commits
eb1ff93d
Commit
eb1ff93d
authored
Dec 18, 2017
by
Dimitry Andric
Browse files
Vendor import of lld trunk r321017:
https://llvm.org/svn/llvm-project/lld/trunk@321017
parent
bafea25f
Changes
812
Expand all
Hide whitespace changes
Inline
Side-by-side
.arcconfig
View file @
eb1ff93d
{
"
project_id
" : "
lld
",
"
repository.callsign
" : "
LLD
",
"conduit_uri" : "https://reviews.llvm.org/"
}
CMakeLists.txt
View file @
eb1ff93d
...
...
@@ -160,8 +160,8 @@ endif ()
# Configure the Version.inc file.
configure_file
(
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/lld/Co
nfig
/Version.inc.in
${
CMAKE_CURRENT_BINARY_DIR
}
/include/lld/Co
nfig
/Version.inc
)
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/lld/Co
mmon
/Version.inc.in
${
CMAKE_CURRENT_BINARY_DIR
}
/include/lld/Co
mmon
/Version.inc
)
if
(
CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR
)
...
...
@@ -210,6 +210,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
)
endif
()
add_subdirectory
(
Common
)
add_subdirectory
(
lib
)
add_subdirectory
(
tools/lld
)
...
...
@@ -221,4 +222,5 @@ endif()
add_subdirectory
(
docs
)
add_subdirectory
(
COFF
)
add_subdirectory
(
ELF
)
add_subdirectory
(
MinGW
)
add_subdirectory
(
wasm
)
CODE_OWNERS.TXT
View file @
eb1ff93d
...
...
@@ -17,3 +17,6 @@ N: Lang Hames, Nick Kledzik
E: lhames@gmail.com, kledzik@apple.com
D: Mach-O backend
N: Sam Clegg
E: sbc@chromium.org
D: WebAssembly backend (wasm/*)
COFF/CMakeLists.txt
View file @
eb1ff93d
...
...
@@ -11,12 +11,12 @@ add_lld_library(lldCOFF
DLL.cpp
Driver.cpp
DriverUtils.cpp
Error.cpp
ICF.cpp
InputFiles.cpp
LTO.cpp
MapFile.cpp
MarkLive.cpp
MinGW.cpp
PDB.cpp
Strings.cpp
SymbolTable.cpp
...
...
@@ -26,22 +26,20 @@ add_lld_library(lldCOFF
LINK_COMPONENTS
${
LLVM_TARGETS_TO_BUILD
}
BinaryFormat
BitReader
Core
DebugInfoCodeView
DebugInfoMSF
DebugInfoPDB
LTO
LibDriver
Object
LTO
MC
MCDisassembler
Target
Object
Option
Support
WindowsManifest
LINK_LIBS
lldCo
re
lldCo
mmon
${
LLVM_PTHREAD_LIB
}
DEPENDS
...
...
COFF/Chunks.cpp
View file @
eb1ff93d
...
...
@@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===//
#include
"Chunks.h"
#include
"Error.h"
#include
"InputFiles.h"
#include
"Symbols.h"
#include
"Writer.h"
#include
"lld/Common/ErrorHandler.h"
#include
"llvm/ADT/Twine.h"
#include
"llvm/BinaryFormat/COFF.h"
#include
"llvm/Object/COFF.h"
...
...
@@ -29,17 +29,14 @@ using llvm::support::ulittle32_t;
namespace
lld
{
namespace
coff
{
SectionChunk
::
SectionChunk
(
Obj
ect
File
*
F
,
const
coff_section
*
H
)
SectionChunk
::
SectionChunk
(
ObjFile
*
F
,
const
coff_section
*
H
)
:
Chunk
(
SectionKind
),
Repl
(
this
),
Header
(
H
),
File
(
F
),
Relocs
(
File
->
getCOFFObj
()
->
getRelocations
(
Header
)),
NumRelocs
(
std
::
distance
(
Relocs
.
begin
(),
Relocs
.
end
()))
{
// Initialize SectionName.
File
->
getCOFFObj
()
->
getSectionName
(
Header
,
SectionName
);
Align
=
Header
->
getAlignment
();
// Chunks may be discarded during comdat merging.
Discarded
=
false
;
Alignment
=
Header
->
getAlignment
();
// If linker GC is disabled, every chunk starts out alive. If linker GC is
// enabled, treat non-comdat sections as roots. Generally optimized object
...
...
@@ -62,7 +59,10 @@ static void applySecRel(const SectionChunk *Sec, uint8_t *Off,
fatal
(
"SECREL relocation cannot be applied to absolute symbols"
);
}
uint64_t
SecRel
=
S
-
OS
->
getRVA
();
assert
(
SecRel
<
INT32_MAX
&&
"overflow in SECREL relocation"
);
if
(
SecRel
>
UINT32_MAX
)
{
error
(
"overflow in SECREL relocation in section: "
+
Sec
->
getSectionName
());
return
;
}
add32
(
Off
,
SecRel
);
}
...
...
@@ -119,7 +119,7 @@ static uint16_t readMOV(uint8_t *Off) {
return
Imm
;
}
static
void
applyMOV32T
(
uint8_t
*
Off
,
uint32_t
V
)
{
void
applyMOV32T
(
uint8_t
*
Off
,
uint32_t
V
)
{
uint16_t
ImmW
=
readMOV
(
Off
);
// read MOVW operand
uint16_t
ImmT
=
readMOV
(
Off
+
4
);
// read MOVT operand
uint32_t
Imm
=
ImmW
|
(
ImmT
<<
16
);
...
...
@@ -129,6 +129,8 @@ static void applyMOV32T(uint8_t *Off, uint32_t V) {
}
static
void
applyBranch20T
(
uint8_t
*
Off
,
int32_t
V
)
{
if
(
!
isInt
<
21
>
(
V
))
fatal
(
"relocation out of range"
);
uint32_t
S
=
V
<
0
?
1
:
0
;
uint32_t
J1
=
(
V
>>
19
)
&
1
;
uint32_t
J2
=
(
V
>>
18
)
&
1
;
...
...
@@ -136,7 +138,7 @@ static void applyBranch20T(uint8_t *Off, int32_t V) {
or16
(
Off
+
2
,
(
J1
<<
13
)
|
(
J2
<<
11
)
|
((
V
>>
1
)
&
0x7ff
));
}
static
void
applyBranch24T
(
uint8_t
*
Off
,
int32_t
V
)
{
void
applyBranch24T
(
uint8_t
*
Off
,
int32_t
V
)
{
if
(
!
isInt
<
25
>
(
V
))
fatal
(
"relocation out of range"
);
uint32_t
S
=
V
<
0
?
1
:
0
;
...
...
@@ -167,36 +169,61 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS,
}
}
static
void
applyArm64Addr
(
uint8_t
*
Off
,
uint64_t
Imm
)
{
// Interpret the existing immediate value as a byte offset to the
// target symbol, then update the instruction with the immediate as
// the page offset from the current instruction to the target.
static
void
applyArm64Addr
(
uint8_t
*
Off
,
uint64_t
S
,
uint64_t
P
)
{
uint32_t
Orig
=
read32le
(
Off
);
uint64_t
Imm
=
((
Orig
>>
29
)
&
0x3
)
|
((
Orig
>>
3
)
&
0x1FFFFC
);
S
+=
Imm
;
Imm
=
(
S
>>
12
)
-
(
P
>>
12
);
uint32_t
ImmLo
=
(
Imm
&
0x3
)
<<
29
;
uint32_t
ImmHi
=
(
Imm
&
0x1FFFFC
)
<<
3
;
uint64_t
Mask
=
(
0x3
<<
29
)
|
(
0x1FFFFC
<<
3
);
write32le
(
Off
,
(
read32le
(
Off
)
&
~
Mask
)
|
ImmLo
|
ImmHi
);
write32le
(
Off
,
(
Orig
&
~
Mask
)
|
ImmLo
|
ImmHi
);
}
// Update the immediate field in a AARCH64 ldr, str, and add instruction.
static
void
applyArm64Imm
(
uint8_t
*
Off
,
uint64_t
Imm
)
{
// Optionally limit the range of the written immediate by one or more bits
// (RangeLimit).
static
void
applyArm64Imm
(
uint8_t
*
Off
,
uint64_t
Imm
,
uint32_t
RangeLimit
)
{
uint32_t
Orig
=
read32le
(
Off
);
Imm
+=
(
Orig
>>
10
)
&
0xFFF
;
Orig
&=
~
(
0xFFF
<<
10
);
write32le
(
Off
,
Orig
|
((
Imm
&
0xFFF
)
<<
10
));
write32le
(
Off
,
Orig
|
((
Imm
&
(
0xFFF
>>
RangeLimit
)
)
<<
10
));
}
// Add the 12 bit page offset to the existing immediate.
// Ldr/str instructions store the opcode immediate scaled
// by the load/store size (giving a larger range for larger
// loads/stores). The immediate is always (both before and after
// fixing up the relocation) stored scaled similarly.
// Even if larger loads/stores have a larger range, limit the
// effective offset to 12 bit, since it is intended to be a
// page offset.
static
void
applyArm64Ldr
(
uint8_t
*
Off
,
uint64_t
Imm
)
{
int
Size
=
read32le
(
Off
)
>>
30
;
Imm
>>=
Size
;
applyArm64Imm
(
Off
,
Imm
);
uint32_t
Orig
=
read32le
(
Off
);
uint32_t
Size
=
Orig
>>
30
;
// 0x04000000 indicates SIMD/FP registers
// 0x00800000 indicates 128 bit
if
((
Orig
&
0x4800000
)
==
0x4800000
)
Size
+=
4
;
if
((
Imm
&
((
1
<<
Size
)
-
1
))
!=
0
)
fatal
(
"misaligned ldr/str offset"
);
applyArm64Imm
(
Off
,
Imm
>>
Size
,
Size
);
}
void
SectionChunk
::
applyRelARM64
(
uint8_t
*
Off
,
uint16_t
Type
,
OutputSection
*
OS
,
uint64_t
S
,
uint64_t
P
)
const
{
switch
(
Type
)
{
case
IMAGE_REL_ARM64_PAGEBASE_REL21
:
applyArm64Addr
(
Off
,
(
S
>>
12
)
-
(
P
>>
12
)
);
break
;
case
IMAGE_REL_ARM64_PAGEOFFSET_12A
:
applyArm64Imm
(
Off
,
S
&
0xfff
);
break
;
case
IMAGE_REL_ARM64_PAGEBASE_REL21
:
applyArm64Addr
(
Off
,
S
,
P
);
break
;
case
IMAGE_REL_ARM64_PAGEOFFSET_12A
:
applyArm64Imm
(
Off
,
S
&
0xfff
,
0
);
break
;
case
IMAGE_REL_ARM64_PAGEOFFSET_12L
:
applyArm64Ldr
(
Off
,
S
&
0xfff
);
break
;
case
IMAGE_REL_ARM64_BRANCH26
:
or32
(
Off
,
((
S
-
P
)
&
0x0FFFFFFC
)
>>
2
);
break
;
case
IMAGE_REL_ARM64_ADDR32
:
add32
(
Off
,
S
+
Config
->
ImageBase
);
break
;
case
IMAGE_REL_ARM64_ADDR32NB
:
add32
(
Off
,
S
);
break
;
case
IMAGE_REL_ARM64_ADDR64
:
add64
(
Off
,
S
+
Config
->
ImageBase
);
break
;
case
IMAGE_REL_ARM64_SECREL
:
applySecRel
(
this
,
Off
,
OS
,
S
);
break
;
default:
fatal
(
"unsupported relocation type 0x"
+
Twine
::
utohexstr
(
Type
));
}
...
...
@@ -224,8 +251,19 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
// Get the output section of the symbol for this relocation. The output
// section is needed to compute SECREL and SECTION relocations used in debug
// info.
SymbolBody
*
Body
=
File
->
getSymbolBody
(
Rel
.
SymbolTableIndex
);
Defined
*
Sym
=
cast
<
Defined
>
(
Body
);
auto
*
Sym
=
dyn_cast_or_null
<
Defined
>
(
File
->
getSymbol
(
Rel
.
SymbolTableIndex
));
if
(
!
Sym
)
{
if
(
isCodeView
()
||
isDWARF
())
continue
;
// Symbols in early discarded sections are represented using null pointers,
// so we need to retrieve the name from the object file.
COFFSymbolRef
Sym
=
check
(
File
->
getCOFFObj
()
->
getSymbol
(
Rel
.
SymbolTableIndex
));
StringRef
Name
;
File
->
getCOFFObj
()
->
getSymbolName
(
Sym
,
Name
);
fatal
(
"relocation against symbol in discarded section: "
+
Name
);
}
Chunk
*
C
=
Sym
->
getChunk
();
OutputSection
*
OS
=
C
?
C
->
getOutputSection
()
:
nullptr
;
...
...
@@ -301,8 +339,8 @@ void SectionChunk::getBaserels(std::vector<Baserel> *Res) {
uint8_t
Ty
=
getBaserelType
(
Rel
);
if
(
Ty
==
IMAGE_REL_BASED_ABSOLUTE
)
continue
;
Symbol
Body
*
Body
=
File
->
getSymbol
Body
(
Rel
.
SymbolTableIndex
);
if
(
isa
<
DefinedAbsolute
>
(
Body
))
Symbol
*
Target
=
File
->
getSymbol
(
Rel
.
SymbolTableIndex
);
if
(
!
Target
||
isa
<
DefinedAbsolute
>
(
Target
))
continue
;
Res
->
emplace_back
(
RVA
+
Rel
.
VirtualAddress
,
Ty
);
}
...
...
@@ -323,12 +361,8 @@ bool SectionChunk::isCOMDAT() const {
void
SectionChunk
::
printDiscardedMessage
()
const
{
// Removed by dead-stripping. If it's removed by ICF, ICF already
// printed out the name, so don't repeat that here.
if
(
Sym
&&
this
==
Repl
)
{
if
(
Discarded
)
message
(
"Discarded comdat symbol "
+
Sym
->
getName
());
else
if
(
!
Live
)
message
(
"Discarded "
+
Sym
->
getName
());
}
if
(
Sym
&&
this
==
Repl
)
message
(
"Discarded "
+
Sym
->
getName
());
}
StringRef
SectionChunk
::
getDebugName
()
{
...
...
@@ -351,7 +385,7 @@ void SectionChunk::replace(SectionChunk *Other) {
CommonChunk
::
CommonChunk
(
const
COFFSymbolRef
S
)
:
Sym
(
S
)
{
// Common symbols are aligned on natural boundaries up to 32 bytes.
// This is what MSVC link.exe does.
Align
=
std
::
min
(
uint64_t
(
32
),
PowerOf2Ceil
(
Sym
.
getValue
()));
Align
ment
=
std
::
min
(
uint64_t
(
32
),
PowerOf2Ceil
(
Sym
.
getValue
()));
}
uint32_t
CommonChunk
::
getPermissions
()
const
{
...
...
@@ -366,7 +400,7 @@ void StringChunk::writeTo(uint8_t *Buf) const {
ImportThunkChunkX64
::
ImportThunkChunkX64
(
Defined
*
S
)
:
ImpSymbol
(
S
)
{
// Intel Optimization Manual says that all branch targets
// should be 16-byte aligned. MSVC linker does this too.
Align
=
16
;
Align
ment
=
16
;
}
void
ImportThunkChunkX64
::
writeTo
(
uint8_t
*
Buf
)
const
{
...
...
@@ -397,10 +431,9 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const {
}
void
ImportThunkChunkARM64
::
writeTo
(
uint8_t
*
Buf
)
const
{
int64_t
PageOff
=
(
ImpSymbol
->
getRVA
()
>>
12
)
-
(
RVA
>>
12
);
int64_t
Off
=
ImpSymbol
->
getRVA
()
&
0xfff
;
memcpy
(
Buf
+
OutputSectionOff
,
ImportThunkARM64
,
sizeof
(
ImportThunkARM64
));
applyArm64Addr
(
Buf
+
OutputSectionOff
,
PageOff
);
applyArm64Addr
(
Buf
+
OutputSectionOff
,
ImpSymbol
->
getRVA
(),
RVA
);
applyArm64Ldr
(
Buf
+
OutputSectionOff
+
4
,
Off
);
}
...
...
@@ -488,8 +521,10 @@ void BaserelChunk::writeTo(uint8_t *Buf) const {
uint8_t
Baserel
::
getDefaultType
()
{
switch
(
Config
->
Machine
)
{
case
AMD64
:
case
ARM64
:
return
IMAGE_REL_BASED_DIR64
;
case
I386
:
case
ARMNT
:
return
IMAGE_REL_BASED_HIGHLOW
;
default:
llvm_unreachable
(
"unknown machine type"
);
...
...
COFF/Chunks.h
View file @
eb1ff93d
...
...
@@ -12,7 +12,7 @@
#include
"Config.h"
#include
"InputFiles.h"
#include
"lld/Co
re
/LLVM.h"
#include
"lld/Co
mmon
/LLVM.h"
#include
"llvm/ADT/ArrayRef.h"
#include
"llvm/ADT/iterator.h"
#include
"llvm/ADT/iterator_range.h"
...
...
@@ -33,9 +33,9 @@ class Baserel;
class
Defined
;
class
DefinedImportData
;
class
DefinedRegular
;
class
Obj
ect
File
;
class
ObjFile
;
class
OutputSection
;
class
Symbol
Body
;
class
Symbol
;
// Mask for section types (code, data, bss, disacardable, etc.)
// and permissions (writable, readable or executable).
...
...
@@ -62,7 +62,6 @@ class Chunk {
// The writer sets and uses the addresses.
uint64_t
getRVA
()
const
{
return
RVA
;
}
uint32_t
getAlign
()
const
{
return
Align
;
}
void
setRVA
(
uint64_t
V
)
{
RVA
=
V
;
}
// Returns true if this has non-zero data. BSS chunks return
...
...
@@ -82,7 +81,7 @@ class Chunk {
// An output section has pointers to chunks in the section, and each
// chunk has a back pointer to an output section.
void
setOutputSection
(
OutputSection
*
O
)
{
Out
=
O
;
}
OutputSection
*
getOutputSection
()
{
return
Out
;
}
OutputSection
*
getOutputSection
()
const
{
return
Out
;
}
// Windows-specific.
// Collect all locations that contain absolute addresses for base relocations.
...
...
@@ -92,23 +91,22 @@ class Chunk {
// bytes, so this is used only for logging or debugging.
virtual
StringRef
getDebugName
()
{
return
""
;
}
// The alignment of this chunk. The writer uses the value.
uint32_t
Alignment
=
1
;
protected:
Chunk
(
Kind
K
=
OtherKind
)
:
ChunkKind
(
K
)
{}
const
Kind
ChunkKind
;
// The alignment of this chunk. The writer uses the value.
uint32_t
Align
=
1
;
// The RVA of this chunk in the output. The writer sets a value.
uint64_t
RVA
=
0
;
// The output section for this chunk.
OutputSection
*
Out
=
nullptr
;
public:
// The offset from beginning of the output section. The writer sets a value.
uint64_t
OutputSectionOff
=
0
;
protected:
// The output section for this chunk.
OutputSection
*
Out
=
nullptr
;
};
// A chunk corresponding a section of an input file.
...
...
@@ -119,23 +117,21 @@ class SectionChunk final : public Chunk {
public:
class
symbol_iterator
:
public
llvm
::
iterator_adaptor_base
<
symbol_iterator
,
const
coff_relocation
*
,
std
::
random_access_iterator_tag
,
Symbol
Body
*>
{
std
::
random_access_iterator_tag
,
Symbol
*>
{
friend
SectionChunk
;
Obj
ect
File
*
File
;
ObjFile
*
File
;
symbol_iterator
(
Obj
ect
File
*
File
,
const
coff_relocation
*
I
)
symbol_iterator
(
ObjFile
*
File
,
const
coff_relocation
*
I
)
:
symbol_iterator
::
iterator_adaptor_base
(
I
),
File
(
File
)
{}
public:
symbol_iterator
()
=
default
;
SymbolBody
*
operator
*
()
const
{
return
File
->
getSymbolBody
(
I
->
SymbolTableIndex
);
}
Symbol
*
operator
*
()
const
{
return
File
->
getSymbol
(
I
->
SymbolTableIndex
);
}
};
SectionChunk
(
Obj
ect
File
*
File
,
const
coff_section
*
Header
);
SectionChunk
(
ObjFile
*
File
,
const
coff_section
*
Header
);
static
bool
classof
(
const
Chunk
*
C
)
{
return
C
->
kind
()
==
SectionKind
;
}
size_t
getSize
()
const
override
{
return
Header
->
SizeOfRawData
;
}
ArrayRef
<
uint8_t
>
getContents
()
const
;
...
...
@@ -163,10 +159,9 @@ class SectionChunk final : public Chunk {
void
addAssociative
(
SectionChunk
*
Child
);
StringRef
getDebugName
()
override
;
void
setSymbol
(
DefinedRegular
*
S
)
{
if
(
!
Sym
)
Sym
=
S
;
}
// Returns true if the chunk was not dropped by GC
or COMDAT deduplication
.
bool
isLive
()
{
return
Live
&&
!
Discarded
;
}
// Returns true if the chunk was not dropped by GC.
bool
isLive
()
{
return
Live
;
}
// Used by the garbage collector.
void
markLive
()
{
...
...
@@ -175,21 +170,16 @@ class SectionChunk final : public Chunk {
Live
=
true
;
}
// Returns true if this chunk was dropped by COMDAT deduplication.
bool
isDiscarded
()
const
{
return
Discarded
;
}
// Used by the SymbolTable when discarding unused comdat sections. This is
// redundant when GC is enabled, as all comdat sections will start out dead.
void
markDiscarded
()
{
Discarded
=
true
;
}
// True if this is a codeview debug info chunk. These will not be laid out in
// the image. Instead they will end up in the PDB, if one is requested.
bool
isCodeView
()
const
{
return
SectionName
==
".debug"
||
SectionName
.
startswith
(
".debug$"
);
}
// True if this is a DWARF debug info chunk.
bool
isDWARF
()
const
{
return
SectionName
.
startswith
(
".debug_"
);
}
// True if this is a DWARF debug info or exception handling chunk.
bool
isDWARF
()
const
{
return
SectionName
.
startswith
(
".debug_"
)
||
SectionName
==
".eh_frame"
;
}
// Allow iteration over the bodies of this chunk's relocated symbols.
llvm
::
iterator_range
<
symbol_iterator
>
symbols
()
const
{
...
...
@@ -213,7 +203,10 @@ class SectionChunk final : public Chunk {
const
coff_section
*
Header
;
// The file that this chunk was created from.
ObjectFile
*
File
;
ObjFile
*
File
;
// The COMDAT leader symbol if this is a COMDAT chunk.
DefinedRegular
*
Sym
=
nullptr
;
private:
StringRef
SectionName
;
...
...
@@ -221,18 +214,12 @@ class SectionChunk final : public Chunk {
llvm
::
iterator_range
<
const
coff_relocation
*>
Relocs
;
size_t
NumRelocs
;
// True if this chunk was discarded because it was a duplicate comdat section.
bool
Discarded
;
// Used by the garbage collector.
bool
Live
;
// Used for ICF (Identical COMDAT Folding)
void
replace
(
SectionChunk
*
Other
);
uint32_t
Class
[
2
]
=
{
0
,
0
};
// Sym points to a section symbol if this is a COMDAT chunk.
DefinedRegular
*
Sym
=
nullptr
;
};
// A chunk for common symbols. Common chunks don't have actual data.
...
...
@@ -369,6 +356,9 @@ class Baserel {
uint8_t
Type
;
};
void
applyMOV32T
(
uint8_t
*
Off
,
uint32_t
V
);
void
applyBranch24T
(
uint8_t
*
Off
,
int32_t
V
);
}
// namespace coff
}
// namespace lld
...
...
COFF/Config.h
View file @
eb1ff93d
...
...
@@ -12,6 +12,7 @@
#include
"llvm/ADT/StringRef.h"
#include
"llvm/Object/COFF.h"
#include
"llvm/Support/CachePruning.h"
#include
<cstdint>
#include
<map>
#include
<set>
...
...
@@ -26,8 +27,7 @@ using llvm::StringRef;
class
DefinedAbsolute
;
class
DefinedRelative
;
class
StringChunk
;
struct
Symbol
;
class
SymbolBody
;
class
Symbol
;
// Short aliases.
static
const
auto
AMD64
=
llvm
::
COFF
::
IMAGE_FILE_MACHINE_AMD64
;
...
...
@@ -39,7 +39,7 @@ static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;
struct
Export
{
StringRef
Name
;
// N in /export:N or /export:E=N
StringRef
ExtName
;
// E in /export:E=N
Symbol
Body
*
Sym
=
nullptr
;
Symbol
*
Sym
=
nullptr
;
uint16_t
Ordinal
=
0
;
bool
Noname
=
false
;
bool
Data
=
false
;
...
...
@@ -79,24 +79,23 @@ struct Configuration {
llvm
::
COFF
::
MachineTypes
Machine
=
IMAGE_FILE_MACHINE_UNKNOWN
;
bool
Verbose
=
false
;
WindowsSubsystem
Subsystem
=
llvm
::
COFF
::
IMAGE_SUBSYSTEM_UNKNOWN
;
Symbol
Body
*
Entry
=
nullptr
;
Symbol
*
Entry
=
nullptr
;
bool
NoEntry
=
false
;
std
::
string
OutputFile
;
std
::
string
ImportName
;
bool
ColorDiagnostics
;
bool
DoGC
=
true
;
bool
DoICF
=
true
;
uint64_t
ErrorLimit
=
20
;
bool
Relocatable
=
true
;
bool
Force
=
false
;
bool
Debug
=
false
;
bool
WriteSymtab
=
true
;
bool
DebugDwarf
=
false
;
bool
DebugGHashes
=
false
;
unsigned
DebugTypes
=
static_cast
<
unsigned
>
(
DebugType
::
None
);
llvm
::
SmallString
<
128
>
PDBPath
;
std
::
vector
<
llvm
::
StringRef
>
Argv
;
// Symbols in this set are considered as live by the garbage collector.
std
::
set
<
Symbol
Body
*>
GCRoot
;
std
::
vector
<
Symbol
*>
GCRoot
;
std
::
set
<
StringRef
>
NoDefaultLibs
;
bool
NoDefaultLibAll
=
false
;
...
...
@@ -107,7 +106,7 @@ struct Configuration {
std
::
vector
<
Export
>
Exports
;
std
::
set
<
std
::
string
>
DelayLoads
;
std
::
map
<
std
::
string
,
int
>
DLLOrder
;
Symbol
Body
*
DelayLoadHelper
=
nullptr
;
Symbol
*
DelayLoadHelper
=
nullptr
;
bool
SaveTemps
=
false
;
...
...
@@ -123,6 +122,11 @@ struct Configuration {
// Used for /opt:lldltopartitions=N
unsigned
LTOPartitions
=
1
;
// Used for /opt:lldltocache=path
StringRef
LTOCache
;
// Used for /opt:lldltocachepolicy=policy
llvm
::
CachePruningPolicy
LTOCachePolicy
;
// Used for /merge:from=to (e.g. /merge:.rdata=.text)
std
::
map
<
StringRef
,
StringRef
>
Merge
;
...
...
@@ -139,6 +143,9 @@ struct Configuration {
StringRef
ManifestUIAccess
=
"'false'"
;
StringRef
ManifestFile
;
// Used for /aligncomm.
std
::
map
<
std
::
string
,
int
>
AlignComm
;
// Used for /failifmismatch.
std
::
map
<
StringRef
,
StringRef
>
MustMatch
;
...
...
@@ -157,13 +164,16 @@ struct Configuration {
uint32_t
MinorImageVersion
=
0
;
uint32_t
MajorOSVersion
=
6
;
uint32_t
MinorOSVersion
=
0
;
bool
CanExitEarly
=
false
;
bool
DynamicBase
=
true
;
bool
AllowBind
=
true
;
bool
NxCompat
=
true
;
bool
AllowIsolation
=
true
;
bool
TerminalServerAware
=
true
;
bool
LargeAddressAware
=
false
;
bool
HighEntropyVA
=
false
;
bool
AppContainer
=
false
;
bool
MinGW
=
false
;
};
extern
Configuration
*
Config
;
...
...
COFF/DLL.cpp
View file @
eb1ff93d
...
...
@@ -61,7 +61,7 @@ class HintNameChunk : public Chunk {
// A chunk for the import descriptor table.
class
LookupChunk
:
public
Chunk
{
public:
explicit
LookupChunk
(
Chunk
*
C
)
:
HintName
(
C
)
{}
explicit
LookupChunk
(
Chunk
*
C
)
:
HintName
(
C
)
{
Alignment
=
ptrSize
();
}
size_t
getSize
()
const
override
{
return
ptrSize
();
}
void
writeTo
(
uint8_t
*
Buf
)
const
override
{
...
...
@@ -76,7 +76,7 @@ class LookupChunk : public Chunk {
// See Microsoft PE/COFF spec 7.1. Import Header for details.
class
OrdinalOnlyChunk
:
public
Chunk
{
public:
explicit
OrdinalOnlyChunk
(
uint16_t
V
)
:
Ordinal
(
V
)
{}
explicit
OrdinalOnlyChunk
(
uint16_t
V
)
:
Ordinal
(
V
)
{
Alignment
=
ptrSize
();
}
size_t
getSize
()
const
override
{
return
ptrSize
();
}
void
writeTo
(
uint8_t
*
Buf
)
const
override
{
...
...
@@ -117,7 +117,6 @@ class NullChunk : public Chunk {
explicit
NullChunk
(
size_t
N
)
:
Size
(
N
)
{}
bool
hasData
()
const
override
{
return
false
;
}
size_t
getSize
()
const
override
{
return
Size
;
}
void
setAlign
(
size_t
N
)
{
Align
=
N
;
}
private:
size_t
Size
;
...
...
@@ -215,6 +214,22 @@ static const uint8_t ThunkX86[] = {
0xFF
,
0xE0
,
// jmp eax
};
static
const
uint8_t
ThunkARM
[]
=
{
0x40
,
0xf2
,
0x00
,
0x0c
,
// mov.w ip, #0 __imp_<FUNCNAME>
0xc0
,
0xf2
,
0x00
,
0x0c
,
// mov.t ip, #0 __imp_<FUNCNAME>
0x2d
,
0xe9
,
0x0f
,
0x48
,
// push.w {r0, r1, r2, r3, r11, lr}
0x0d
,
0xf2
,
0x10
,
0x0b
,
// addw r11, sp, #16
0x2d
,
0xed
,
0x10
,
0x0b
,
// vpush {d0, d1, d2, d3, d4, d5, d6, d7}
0x61
,
0x46
,
// mov r1, ip
0x40
,
0xf2
,
0x00
,
0x00
,
// mov.w r0, #0 DELAY_IMPORT_DESCRIPTOR
0xc0
,
0xf2
,
0x00
,
0x00
,
// mov.t r0, #0 DELAY_IMPORT_DESCRIPTOR
0x00
,
0xf0
,
0x00
,
0xd0
,
// bl #0 __delayLoadHelper2
0x84
,
0x46
,
// mov ip, r0
0xbd
,
0xec
,
0x10
,
0x0b
,
// vpop {d0, d1, d2, d3, d4, d5, d6, d7}
0xbd
,
0xe8
,
0x0f
,
0x48
,
// pop.w {r0, r1, r2, r3, r11, lr}
0x60
,
0x47
,
// bx ip
};
// A chunk for the delay import thunk.
class
ThunkChunkX64
:
public
Chunk
{
public:
...
...
@@ -259,17 +274,45 @@ class ThunkChunkX86 : public Chunk {
Defined
*
Helper
=
nullptr
;