Before 9306f69a61, we completely ignored
duplciate symbol errors in IR object files. After that commit, we've
been accidentally reporting duplicate comdat symbols as errors.
Fixes https://github.com/rui314/mold/issues/1434
It looks like Linux is going to support CET only on x86-64 (i.e. endbr64),
and it is very unlikely that x86-32 will get CET support. So I'll remove
the instruction from the code we generate for x86-32.
Removes the temporary file created by the compiler
from the dependency list created with --dependency-file.
Without this build systems will never report "Nothing to do",
but always do a re-link of the final object.
R_X86_64_CODE_5_{GOTPCRELX,GOTTPOFF,GOTPC32_TLSDESC} and
R_X86_64_CODE_6_{GOTPCRELX,GOTPC32_TLSDESC} are defined just for
completeness (*), so we've implemented all APX relocations with
this change.
* https://gitlab.com/x86-psABIs/x86-64-ABI/-/merge_requests/53
These relocations are for Intel APX (Advanced Performance Extension)
that extends the number of general-purpose registers from 16 to 32.
GNU assembler that comes with GCC 14 or newer can compile the test code.
I believe this is just due to the lower number of users on ARM64
runners compared to x86. However, based on my measurements, ARM64
builds all binaries in 1h30m, whereas x86 takes 2h30m.
We need to stop using `grep -q` because grep terminates immediately after
finding the first match with `-q`, causing SIGPIPE to the process on the
other side of the pipe.
Previously, these symbols were defined relative to a section. That is
logically correct, because the runtiem is supposed to apply IREL
relocs between `__rela_iplt_start` and `__rela_iplt_end`, so their
actual locations shouldn't matter if there's no IREL relocs (i.e. they
refer to the same location.)
However, under some circumstances, glibc reads `__rela_iplt_start`
before applying base relocations and `__rela_iplt_end` after applying
them due to compiler instruction reordering.
Therefore, we need to make them absolute symbols that don't require
base relocations.
Fixes https://github.com/rui314/mold/issues/1407
If both --separate-debug-info and --compress-debug-info are given, we want to
compress debug sections in background so that the delay caused by compression
is not visible to users.
I didn't know if Azure ARM64 servers support ARM32 instructions, but
apparently they do because running ARM32 code is much faster on ARM64
GitHub Actions runners.
Previously, 4 bytes were allocated for each relocation in a text
section to store the number of bytes removed before each relocation.
Now, only the locations where bytes are removed are stored.
This commit improves performance by ~4% when linking clang-19 for RISC-V.
Previously, we allocate 4 byte struct for each relocation to store a
reference to a thunk in case the relocation needs to branch to a thunk.
Most references are null because most relocations don't need thunks.
This commit changes how we manage references to range extension thunks.
Now, thunk addresses are stored to symbols rather than to relocations.
Linking clang-19 for ARM64 is now ~7% faster than before.
ELF Application Binary Interface s390x Supplement Version 1.6.1, p.58 says
that "The doublewords at _GLOBAL_OFFSET_TABLE_[1...2] are reserved for
system use."
We had previously reserved GOT[0] and GOT[1], but we did not reserve GOT[2].
It's most likely that GOT[2] is not actually in use, as it appears that
mold-linked programs work without it. But we need to adhere to the psABI.
On RHEL 10, GCC is configured with the `--with-arch_64=x86-64-v3`
option, which makes it implicitly use the `-march=x86-64-v3`
command-line flag by default.
This breaks the `arch-x86_64-ifunc-alias` test: since the `x86-64-v3`
microarchitecture level includes SSSE3 and AVX2, GCC appears to
interpret the `default` and `ssse3,avx2` targets as the same thing, and
omits generating a resolver function.
Fix the test by forcing GCC's target architecture to the `x86-64`
baseline.
Switch from Docker to Podman for container builds and remove unused
buildx steps. Also this commit updates GitHub Actions workflows to use
redhat-actions/podman-login and docker/setup-qemu-action@v3, removing
references to Docker Buildx.
Fixes: ec1d7120aa ("Use docker only on GitHub Actions")
Signed-off-by: Ruowen Qin <[email protected]>
Debian 11 ships GCC 10 and CMake 3.18, which happen to be precisely the
minimum versions required for building mold from source.
Add a CI pipeline to prevent future commits from inadvertently breaking
compatibility with older toolchains.
Linux upstream has reverted commit 2a010c412853 ("fs: don't block
i_writecount during exec") and the change is merged in the 6.13 cycle.
This means the executable overwriting behavior can be restored on Linux
kernel version 6.13 or later.
Note that there is probably not much we can do for 6.11 / 6.12 kernels.
Although the reversion is backported, many distros do not use upstream
sub-version numbers which means we cannot determine whether the kernel
has this reversion based on its version number.
Signed-off-by: Jinghao Jia <[email protected]>
Even though 16 KiB is the common page size, the Linux kernel for
LoongArch supports 64 KiB pages. Currently, mold-generated binaries
run only on systems with <=16 KiB page.
Note that unlike GNU ld, increasing the maximum page size doesn't
increase the on-disk binary size of generated binaries.
This is an alternative to https://github.com/rui314/mold/pull/1383
The upcoming version of GNU binutils's ld now treats arguments for
`--package-metadata` as percent-encoded strings and decodes them before
writing to .note.package.
Additionally, GNU ld will support `%[<charname>]`, where `<charname>` can be
`comma`, `lbrace`, `rbrace`, `quot`, or `space`. This feature could improve
readability when manually writing command-line arguments.
That said, I don't believe we need to support these metacharacters, for the
following reasons:
1. This option is specifically designed for distribution package maintainers
to embed metadata into binaries, and is not intended for general use.
2. Command-line arguments for this option are always generated by build
scripts, not written manually.
If we need these character names, we can add that later.
Furthermore, GNU ld does not appear to report errors for orphan '%'
characters that are not followed by valid hex values; instead, it simply
passes through such characters. I find this behavior fragile. We will report
an error for invalid '%' characters.
With these considerations in mind, I'll just rename the existing
`--encoded-package-metadata` option to `--package-metadata`.
In case ctest fails in the CI, no error logs are printed. This makes
debugging harder.
So run ctest with `--output-on-failure` to ease debugging in case of
failures.
Combining mimalloc and AddressSanitizer triggers a segmentation fault in
many tests.
Combining mimalloc and ThreadSanitizer leads to duplicate symbols for
the `new` and `delete`
operators, causing the build to fail.
Example message from a failed GitHub Actions build:
```
mold: error: duplicate symbol:
third-party/mimalloc/libmimalloc-debug.a(alloc.c.o):
/usr/lib/llvm-18/lib/clang/18/lib/linux/libclang_rt.tsan_cxx-x86_64.a(tsan_new_delete.cpp.o):
operator delete(void*, std::align_val_t)
```
This allows the compiler to make sure that the implementation of
`set_mimalloc_options()` matches its declaration.
More importantly, it indirectly pulls in `config.h`, where the macros
`MOLD_USE_SYSTEM_MIMALLOC` and `MOLD_USE_MIMALLOC` are conditionally
defined. Without these, the build configuration is ignored.
We don't need to create a copy of license files for third-party software
as we keep an original license file for each subdirectory. It is probably
a bit risky to create copies of license files because it is easy to become
out-of-sync. So I'll just remove this file.
If running in big-endian mode, SH4 processors expects both data and
instructions to be encoded in big-endian. Therefore, nop need to be
reversed for sh4be.
This commit adds experimental big-endian SH4 support. Since we already
support little-endian SH4, it wasn't too difficult to support its big-
endian variant.
Some tests related to C++ exceptions fail due to mysterious errors.
I don't have time to debug it, so I'll disable them for now.
Closes https://github.com/rui314/mold/issues/1273
Including mimalloc-new-delete.h overrides new and delete operators
with mimalloc. If a user choose not to use mimalloc, we shouldn't
include that file.
https://github.com/rui314/mold/issues/1355
RHEL 8.7's version of dwarfdump (2018-01-29) is too old to recognize the
SHF_COMPRESSED flag in debug info, so the compress-debug-sections test
fails despite the debug sections being compressed as intended.
To fix this, we will use readelf to dump information about the
executable. The COMPRESSED flag can be verified using this.
It looks like only the presence of the entry is important, but by
convention, GNU ld and lld set 0 to a DT_AARCH64_VARIANT_PCS dynamic
entry, so we should follow suit.
Keeping DEC Alpha support is difficult because there are no Alpha
machines available for toolchain developers, and even if there were,
no modern Linux distros still support Alpha. For example, Debian
dropped Alpha support in Debian 6.0. As a result, I cannot test my
linker with real-world programs.
In fact, I believe mold has never been able to link real-world large
programs. Object files for Alpha are compiled with the small code
model by default, so it is not easy to support it in the linker.
There's no means to verify that my implementation is correct for Alpha
because Alpha's psABI has never been published by DEC. The most
"reliable" source of correctness is GNU ld's source code and comments.
Last but not least, I believe there are literally zero mold/Alpha
users. Unlike some other retro computers like the m68k, Alpha doesn't
seem to get much love from the community, perhaps because the
availability of Alpha machines was limited in the first place, even in
the 90s.
Therefore, I'll remove Alpha support now. If there's someone who wants
to keep it, we can resurrect and re-test it.
This change should make the mold binary size a little smaller.
This commit reverts 0612ea41f1 and
instead solves the original issue with a different approach.
Now, if a hidden symbol was resolved to a DSO symbol, we'll redo
symbol resolution so that the symbol won't be resolved to the same one
next time.
This should fix our build-all buildbot.
Assume both `foo.a` and `bar.so` define the same symbol `baz`.
If `baz`'s symbol visibility is hidden, it needs to be resolved within
the output file, i.e., from `foo.a`. However, previously, such symbol
was resolved to the one in `bar.so`.
To fix the problem, we'll lower the symbol priority for DSOs.
Fixes https://github.com/rui314/mold/issues/1342
Word-size absolute relocations, such as R_X86_64_64, are special from
the linker's point of view because only such symbols can be promoted
to dynamic symbols. This patch handles them separately.
* Fix infinite loop in `split_by_comma_or_colon()`.
The mere presence of a `,` or a `:` in the input string would make the
function enter an infinite loop, effectively freezing the program until
all available memory was exhausted. The string position in the loop was
not incremented past the `,` or the `;` character that had just been
read.
The function is currently used only in the `--exclude-libs` option. The
freeze is reproducible with:
```bash
$ mold --exclude-libs foo,bar
```
The longer the string after the first `,` or `:` is, the faster memory
exhaustion is reached.
* Skip empty parts in `split_by_comma_or_colon()`.
The LoongArch extreme code model uses the following instructions to
materialize a 64-bit value in a regiter.
pcalau12i $t1, %pc_hi20(g2)
addi.d $t0, $zero, %pc_lo12(g2)
lu32i.d $t0, %pc64_lo20(g2)
lu52i.d $t0, $t0, %pc64_hi12(g2)
The previous relocation formula expected that `page(pc)` would be
consistent for all the instructions, but this assumption is incorrect
if the instruction sequence crosses a 4 KiB boundary.
Now, the LoongArch psABI requires that the machine instructions must be
consecutive, and the relocations for lu32.d and lu52i.d uses
`page(pc - 8)` and `page(pc - 16)` instead of `page(pc)`.
This psABI change gave me an impression that the LoongArch's extreme code
model was poorly designed and inadequately tested. If these instructions
must be consecutive, only a single relocation referring to the beginning
of the instructions would suffice, which relocates all the following four
instructions at once.
Maybe we do not need to support the relocations for the extreme code model
because the code model was buggy at the spec level, which suggests that no
one is using them. But I'm not sure if it is safe to remove them, so let's
just follow the psABI change.
Old zlib does not support crc32_z. The difference between the two is
that crc32() takes an input size as an unsigned int while crc32_z()
takes as size_t. For our use case, size is guranteed to be short, so
crc32() is safe to use.
It looks like emitting PCADDU18I + JIRL instead of just BL for function
calls is a way to go, so we don't want to bother to maintain range
extension thunks for the psABI.
Since no other linkers support range extension thunks for LoongArch other
than us, removing the support should be OK.
Previously, functions that are referred to only by section symbols were
not considered address-taken, and we always rewrote endbr64s with NOPs for
such functions. That caused a runtime fault when such function was called
indirectly.
Now, endbr64s for such symbols are retained.
I tried to build clang-19 as a release build with and without `-z
rewrite-endbr` and counted the number of endbr64 instructions in each
binary. Here is the result:
Before: 110,615
After: 91,799
So the feature reduces the number of gadgets by 17%. Both binaries worked
fine with Intel SDE CPU emulator with `-cet 1 -cet_raise 1`, so I think
it's finally working as expected.
I also tried to build mold itself with and without the feature. Here is
the result:
Before: 27,430
After: 17,725
This is a 35% reduction. I confirmed that mold built with `-z rewrite-endbr`
can self-host under Intel SDE.
The rewrite_endbr pass is extremely fast. It took only 7 milliseconds
for a ~210 MiB clang-19 binary on my Threadripper 7990X machine. We
may want to consider enabling it by default at some point.
glibc's `__register_frame_info_bases` expect that it can read a terminator
if a .eh_frame is empty. Removing the section completely caused a crash bug
on Alpine Linux with musl as libc.
Specifically, mold-generated binaries crash if all the following
condition were met:
1. musl is used as a libc
2. .eh_frame is empty
3. libgcc_s.so is linked
Prior to 06b592683c, condition (3) was not
usually satisfied, so we didn't notice this issue. Now, the shared library
is linked against almost all output files because the file is referenced by
`__deregister_frame_info`.
https://github.com/bminor/glibc/blob/910aae6e5a2196938fc30fa54dd1e96f16774ce7/sysdeps/generic/unwind-dw2-fde.c#L105-L107
Fixes https://github.com/rui314/mold/issues/1309
Specifying the compiler flag `-Wl,--package-metadata=<JSON>` might not
work, because the shells might eat the quotation marks and the compiler
splits the JSON at the commas.
Ubuntu tried to using a specs file to set `--package-metadata` but that
turned out to be too fragile. autopkgtests might use the compiler flags
but the needed environment variables are not set in the test
environment. Debugging a crash of an application build with the -spec
parameter lacks the environment variables. People like to iteratively
continue building the software in the build directory while hacking on
the package and then have no environment variable set.
So introduce a `--encoded-package-metadata` linker flag that takes a
percent-encoded JSON. Percent-encoding is used because it is a
standard and simple to implement.
Bug-Ubutru: https://bugs.launchpad.net/bugs/2071468
Signed-off-by: Benjamin Drung <[email protected]>
Previously, we find a string in a mergeable string section by offset
after adding a relocation addend to a symbol value. Now, we find a
string just by a symbol value and then add a relocation addend later.
Assume a mergeable section containing two strings as an example.
foo\0bar\0
^ ^
.L1 .L2
Previously, a relocation referring to .L2 - 1 referred to the end of
.L1. Now, it refers to one byte before .L2.
Section symbol is an exception to this rule, because it seems it's
what the compiler is assuming. The rules seem arbitrary, but it looks
like we need them for the compatibility with existing object files.
Fixes https://github.com/rui314/mold/issues/1300
This option is to separate debug info to a different file. The debug
info file's filename is stored to the main output file's .gnu_debuglink
section. gdb can read the section contents and followg the link to
find debug info in another file.
Fixes https://github.com/rui314/mold/issues/1294
It is not clearly defined when undefined weak symbols are resolved.
It looks like there are two possible approaches:
1. Promote all weak undefined symbols to dynamic ones so that they'll
have another chance to be resolved at load-time, or
2. Promote weak undefined symbols to dynamic ones only when there are
definitions in other DSOs at link-time.
(1) provides the maximum flexibility. For example, consider a main program
that has a weak undefined symbol `foo` and there's no DSO that defines it
at link-time. In (1), `foo` gets promoted to a dynamic symbol, so that one
of its depending DSO is upgraded to define `foo`, the main executable's
`foo` is resolved to that symbol at load-time. On the other hand, in (2),
`foo` would have already been converted to an absolute symbol at address
zero at link-time, so you need to rebuild the main executable to use the
new definition of `foo` in the shared library.
However, (1) is not compatible with copy relocations. This is because we
need to know the size of the symbol when creating a copy relocation, but
that information is not available unless we have a definition. It's also
not compatible with canonical PLTs because canonical PLTs have non-zero
addresses and therefore weak undefined symbols would always be resolved to
non-zero addresses.
As a workaround, GNU ld promotes weak undefs to dynamic symbols only when
they don't need copy relocations or canonical PLTs. In other words, weak
undef's behavior is different between -fPIC and -fno-PIC. In the former
case, they become dynamic symbols, and vice versa.
I don't think that workaround is a good one. So, mold took the second
approach.
There is, however, another thing to consider. What if we can find a
defined symbol in a DSO that is specified as `-as-needed`? Previously,
mold did not mark the library as "needed" and converted the weak undef
into an absolute symbol.
However, libstdc++ assumes that if weak undef symbol
`__pthread_key_create` is not resolved, it assumes that multi-threading is
not used in the executable, which resulted in a mis-detection with mold.
Therefore, this patch changes the mold's behavior so that it makes weak
undefs to keep DSOs "needed".
Fixes https://github.com/rui314/mold/issues/1286
Use $CXX instead of $CC to detect whether C++ programs could be built
statically. Add function test_cxxflags for convenience.
Fix test error in an environment where C++ programs cannot be built
statically, with error like:
mold: fatal: library not found: c++
Signed-off-by: Yao Zi <[email protected]>
The interaction between these flags are unnecessarily complicated,
but it looks like `--undefined=ignore-in-object-files` needs to
share the same internal flag as `-z defs` so that they override
each other.
Fixes https://github.com/rui314/mold/issues/1270
Teaching the compiler that `buflen` cannot be negative and also doesn't
take a large value allows it to optimize code a little bit more than
it currently does.
I couldn't find any report that the reduced round version is broken
despite being used at a lot of places (e.g. Rust's hash table uses
SipHash-1-3). So I assume it's secure.
`which` isn't in POSIX and several Linux distributions are trying to
remove it from their base system, see e.g. https://lwn.net/Articles/874049/.
Just use `command -v` which is POSIX.
Signed-off-by: Sam James <[email protected]>
We use Aho-Corasick string search algorithm for version script.
If all symbols in a version script do not start with '*', we can
terminate the algorithm early.
I believe some version of objcopy corrupts an object file when
renaming a section. In this change, I use sed instead of objcopy
as a workaround.
Fixes https://github.com/rui314/mold/issues/1244
It looks like Clang recognize `#pragma GCC unroll`. Instead of adding
more C preprocessor directives here, I'd like to rely on the default
compiler optimizations.
If a synthesized symbol overrides an imported symbol, the symbol's
`is_imported` flag must be reset.
Technically, `compute_import_export` is called too early, and this
function call should be moved after `create_synthetic_sections`.
However, fixing the issue that way was very hard because until we
create output sections, we don't know what __start_/__stop_ symbols
need to be synthesized, but in order to create output sections,
we need to compute import/export bits.
So, in this commit, we simply reset `is_imported` flag for
synthesized symbols.
https://github.com/rui314/mold/pull/1236
Previously, .so and .a were of the same priority and therefore symbols
in those were resolved based on their positions in the command line;
whichever file appears first in the command line took precedence.
Here is the problem we are trying to solve with this change: KiCad
passes unnecessary .a files to the linker along with some .so files.
Some symbols are defined both by .a and by .so.
If a symbol is resolved from .a, the linker pulls out the file from
the archive, but because the .a file does not really provide a
complete set of object files, it ended with "undefined symbol" error.
If a symbol is resolved from .so, everything is fine.
This is arguably a bug in KiCad, or at least depending on the order of
files in the command line is very fragile. But maybe this change could
fix the issue without too much side effects. So let's see how it goes.
Fixes https://github.com/rui314/mold/discussions/1234
RISC-V psABI requires that symbol to be exported from an executable
if there's a GP-relative reference. For simplicity, we always export
it from executable as long as it has a .dynamic section.
https://github.com/rui314/mold/issues/1222
Runtime doesn't care where mergeable sections are, but it's reported
that Valgrind does. So, grouping mergeable sections just doesn't seem
to make sense.
https://github.com/rui314/mold/pull/1223
libtool mistakes mold 2.4.1 as GNU ld 2.4 and wrongly concludes that our
linker does not support anonymous versioning and suppresses some uses of
version scripts. That has been causing subtle compatibility issues with
programs that use libtool to create their .so files.
Here is the code that mistakes our linker as GNU ld:
https://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4?h=v2.4.7#n5066
As a workaround, I decided to bump our linker version so that the version
number is sufficiently large. This is admittedly ugly but I think it's the
simplest solution for the problem.
Our ConcurrentMap uses linear probing to find unused hash table entry.
It gives up if 128 consective slots are occupied, and the whole process
dies with the "ConcurrentMap is full" error message. So our hash
function's quality must be high.
For .gdb_index, we used to use gdb_index() to compute keys for the
ConcurrentMap. It turned out that the function's quality is poor,
generating very similar output for short strings.
This commit changes the hash function to xxhash.
Fixes https://issues.chromium.org/issues/40276991#comment5
Previously, mold marked an imported symbol as a strong one if the
symbol came from a DSO and was exported as a strong symbol by the DSO.
This logic resulted in a miscomputation of the weakness bit, causing a
compatibility issue with other linkers.
Now, an imported symbol is marked as strong only when there's at least
one strong reference to it. In other words, if all references to an
imported symbol are weak, the symbol will be imported as a weak one.
Fixes https://github.com/llvm/llvm-project/issues/83080
Prior to this change, links on Windows were failing with:
mold: fatal: <input file>: CreateFileMapping failed: 5
"5" is the Windows error code for ERROR_ACCESS_DENIED.
Use native Windows file API in MappedFile. Create read only mapping with
FILE_MAP_COPY view because the file mapping contents may be modified in
process but should not be written back.
On Windows, it is important that files are opened in "binary" mode to
avoid automatic "text" mode conversions which can result in "corrupted"
input/output.
Previously, mold didn't merge sections with the same name but different
section flags into a single section. This behavior is different from other
linkers and caused a compatibility issue.
Now, mold merges input sections by their names and types.
Fixes https://github.com/rui314/mold/issues/1196
std::string is a non-trivial type, this change ensures its
copy-ctor and dtor don't get called.
Found by Clazy (range-loop-reference)
Signed-off-by: Christoph Grüninger <[email protected]>
illumos is a descendent of Solaris/OpenSolaris, and treats
symbols with shndx=SHN_ABS and st_value=0 specially, such that
they should be marked imported. This change adds a special
case for this behavior, wrapped up in a function that #ifdef's
out on other platforms. With this patch, executables linked
with mold on illumos run; without it, they do not.
The original behavior was spotted by Luqman Aden (@luqmana).
This also patches a small bogon in the third-party `mimalloc`
code. I've sent that same fix upstream, but so far the
maintainer has not resonded, so replicate here.
Fixes#1183
Signed-off-by: Dan Cross <[email protected]>
When removing symbols, the indices in .llvm_addrsig also needs to be
updated, but binutils is not aware of this and leaves the table in a
corrupt state.
Use the same test as what LLD uses to reject potentially corrupted addrsig
sections.
Unfortunately, testing this seems tricky. While producing a file with OOB
addrsig index is not hard, it's hard to consistently trigger a segfault
with that access.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Previously, if two or more VERSION clauses match to the same symbol,
the first one took precedence. This was incompatible with GNU ld, which
gives the last one the highesth priority.
This change inverted the priority so that the last one will take
precedence other the others.
Fixes https://github.com/rui314/mold/issues/1158
Using ftruncate() creates holes inside files, that on first (write) page
fault gets allocated an actual disk block. There are several
disadvantages with this:
- Allocating block one-by-one is slower than doing it all at once.
- As we write to the output in parallel the write order is not exactly
sequential. The allocated blocks can also be out-of-order and make the
on-disk representation fragmented.
Instead, use posix_fallocate() which allocates a contiguous on-disk block
(if possible). It's arguably a better fit for linker output, since holes
are unlikely to be present after writing all the output (any contiguous
zeroes should just go into .bss).
I benchmarked this by linking mold with debug symbols. On an 8-core
desktop, it is 5% (1.0s -> 0.95s) faster, but on a 64-core workstation it
is actually 40% slower (0.37s -> 0.52s). The total amount of System time
is reduced (6.7s -> 5.2s), however. I suspect that the reduced page fault
work ends up causing more lock contention.
Despite potential regression on high-core systems I still think this
change is justified because of the better on-disk layout.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Previously, we always tried to demangle a symbol name as a Rust
symbol first and then attempted to demangle it as a C++ symbol.
This resulted in an incorrect demangled result, as the Rust legacy
mangling scheme is not distinguishable from C++.
This patch fix the issue by adding the "is_rust_obj" flag to the
ObjectFile. We try to demangle a symbol as a Rust one before as a C++
only if the flag is true.
Fixes https://github.com/rui314/mold/issues/1159
A `.eh_frame` section contains data for exception handling. Usually,
an object file contains only one `.eh_frame` section, which explains
how to handle exceptions for all text sections in the same object file.
However, it appears that, in rare cases, we need to handle object
files containing multiple `.eh_frame` sections. An example of this is
the `/usr/lib/clang/17/lib/x86_64-redhat-linux-gnu/clang_rt.crtbegin.o`
file, which is provided by the `compiler-rt` package of Fedora 39.
Specifically, I'm using the `quay.io/fedora/fedora:39` Docker image.
The file contains two `.eh_frame` sections.
One `.eh_frame` in the file is of type `STT_X86_64_UNWIND` and the
other is of `STT_PROGBITS`. It's possible that the file was created
with `ld -r`, and the linker failed to merge the two incoming
`.eh_frame` sections into one output section due to the difference in
section types.
We did not expect such inputs and consequently produced corrupted
output files.
This commit improves our linker so that mold can handle multiple
`.eh_frame` sections in a single object file.
Fixes https://github.com/rui314/mold/issues/1157
Previously, symbol names or wildcard patterns in version script files
were processed strictly from top to bottom. When a single symbol
matches two or more patterns, the first one was given precedence.
However, GNU ld appears to treat exact matches differently, assigning
them higher precedence over wildcard patterns. This discrepancy led to
programs linked with Qt 6.6.1 using mold failing to launch.
Fixes https://github.com/rui314/mold/issues/1158
It had been assumed that the TLSDESC code seqeunce looks like this:
lea 0(%rip), %rax
R_X86_64_GOTPC32_TLSDESC foo
call *(%rax)
R_X86_64_TLSDESC_CALL foo
However, LLVM seems to also emit something like this:
lea 0(%rip), %reg
R_X86_64_GOTPC32_TLSDESC foo
...
mov %reg, %rax
...
call *(%rax)
R_X86_64_TLSDESC_CALL foo
That means when we rewrite the LEA instruction to relax the code
sequence, we need to handle destination registers other than %rax.
The wrong assumption caused a program crash as reported as
https://bugs.gentoo.org/914849.
This is a new experimental flag to make room at the end of PHDR
so that post-processing tools can add more entries as needed.
Fixes https://github.com/rui314/mold/issues/1148
Debian 8 was released in April 2015, which is old enough for
binary distribution. Previously, we used to use Debian 10 (Bullseye),
which was released in July 2019.
--dynamic-list, --export-dynamic-symbol and --export-dynamic-symbol-list
have different semantics for executables and DSOs. If the output is an
executable, they specify a list of symbols that are to be exported.
If the output is a shared object, they specify the list of symbols that
are to be interposable.
mold havne't implemented the latter semantics. This commit fixes that
issue.
Fixes https://github.com/rui314/mold/issues/1071
.init_array/.fini_array haven't completely replace .ctors/.dtors, so
we need to convert .ctors/.dtors to .init_array/.fini_array.
Fixes https://github.com/rui314/mold/issues/1113
Previously, we didn't emit a dynamic relocation for a statically-
initialized function pointer pointing to an ifunc on POWER10, e.g.
int fn() __attribute__((ifunc("resolve_fn")));
void *ptr = fn;
Fixes https://github.com/rui314/mold/issues/1142
For --relocatable output, we need to pass through these attributes
for correctness. With this change, we'll have more .rodata sections
such as .rodata.str1.1, rodata.str1.4, etc. in the final executable,
but that should be fine because the runtime doesn't care about
section tables at all. The table isn't even loaded to memory at runtime.
IFUNC symbols are resolved at process startup by executing the function
that the symbol points to. This is used to select the "best" function at
runtime; for instance, the runtime may choose a faster version of memcpy
that uses SIMD instructions if they are available on the current system.
Thus, an IFUNC symbol has two addresses: the initial address (or the
resolver's address) and the resolved address, which is the return value of
the resolver.
In position-independent executables (PIEs), function pointers are loaded
from the GOT indirectly, and symbols are not directly referenced. In such
executables, the initial value of the GOT slot for an IFUNC symbol
contains the resolver address, and this is overwritten at runtime to the
resolved address upon process startup. When user code takes a pointer to
an IFUNC, it always reads the resolved address from GOT.
In contrast, position-dependent executables (PDEs) may have instructions
that directly refer to an IFUNC symbol, such as movabs on x86-64. The GOT
entry for an IFUNC holds the resolved address, so any direct reference
must also produce the resolved address to maintain pointer equality.
(C/C++ standards require that two pointers must be equal if and only if
they are taken for the same symbol.)
Previously, we emitted text relocations to modify instruction operands.
However, text relocations are undesirable and not always reliable. For
example, on ARM64, multiple instructions are used to materialize a
symbol's address, and it's not feasible to issue a dynamic relocation to
alter those instructions since the dynamic loader generally can only
modify 32-bit or 64-bit words.
In this commit, I have adopted a different strategy. An IFUNC symbol now
occupies two consecutive GOT slots in a PDE. The first slot holds the
symbol's PLT address, and the second slot holds the resolved address. The
PLT address is consistently used as the symbol's address throughout the
process, while the second slot is used only by the PLT entry to jump to
the resolved address.
This method ensures pointer equality without the need to emit text
relocations for IFUNC symbols in PDEs.
It seems R_LARCH_PCALA_LO12 is sometimes used against JIRL even though
such use case is incorrect as per the psABI.
At least, `/usr/lib/loongarch64-linux-gnu/libc_nonshared.a(atexit.oS)`
on `cfarm400.cfarm.net` contains such relocation.
We need this patch to self-host mold on that cfarm machine.
Specifically, .llvm.call-graph-profile is always REL even on x86-64.
We can safely ignore the relocation table because it contains only
R_NONE relocations.
Fixes https://github.com/rui314/mold/issues/653
The test expects the output format given by `llvm-readelf`:
```
5: 0000000000010698 0 FUNC GLOBAL DEFAULT [VARIANT_PCS] 13 foo
```
However, in GNU's `readelf` implementation the symbol name comes first:
```
5: 0000000000010698 0 FUNC GLOBAL DEFAULT 13 foo [VARIANT_PCS]
```
Replace the regular expression with two `grep` calls piped together to
support both output formats.
Signed-off-by: Christoph Erhardt <[email protected]>
`test_cflags` uses $CC to test if a given flag is supported, so
we should use $CC instead of $GCC for the rest of the file.
Fixes https://github.com/rui314/mold/issues/1128
This reverts commit 967006479f because
it made the linker to crash. TLSDESC doesn't seem to work even with
GNU ld on ARM32 musl systems, so I'll disable the test.
Fixes https://github.com/rui314/mold/issues/1116
Despite the extern template items Clang 14 seems to insist on instantiating
elf_main(), with the hilarious consequence of the function being duplicated
quadratically to the number of archs.
Move this to a different CU so that the compiler cannot possibly
instantiate it more than once. This significantly speeds up compilation
related to main.cc.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Despite the extern template items Clang 14 seems to insist on instantiating
elf_main(), with the hilarious consequence of the function being duplicated
quadratically to the number of archs.
Move this to a different CU so that the compiler cannot possibly
instantiate it more than once. This significantly speeds up compilation
related to main.cc.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Compiler warnings have the potential to uncover real bugs before they
make it into a commit. For example, the accidental fallthrough
introduced by commit 713d81947a and fixed
by commit 49f38828d1 could have been
detected by GCC.
Remove `-Wunused-variable` since it is implied by `-Wall`.
Add `-Wno-unused-parameter` to suppress warning spam regarding unused
parameters.
Signed-off-by: Christoph Erhardt <[email protected]>
This fixes the following compiler warning:
> enumerated and non-enumerated type in conditional expression [-Wextra]
Signed-off-by: Christoph Erhardt <[email protected]>
endbr64 is a relatively new x86 instruction to mark a location to which an
indirect jump instruction can transfer control. If the control-flow
integrity is turned on (i.e., endbr64 is effective), an indirect jump can
only target an endbr64 or raise a runtime exception. This mechanism makes
some types of control hijacking attacks, such as ROP or JOP, very hard
because an attacker can no longer jump to an arbitrary location.
If `-fcf-protection` is given, GCC emits an endbr64 at the beginning of
each global function conservatively because the address of that function
might be used by other translation units.
In reality, most function addresses aren't taken, so the conservative
assumption ends up emitting lots of unnecessary endbr64 instructions.
This not only bloats the code but also weakens security because an
attacker would have more locations to attack.
The new linker option, `-z rewrite-endbr`, is designed to mitigate this
situation. The linker is in a position to conduct whole-program analysis
on the input files and determine functions whose addresses have never been
taken. If `-z rewrite-endbr` is given, mold performs that analysis and
rewrites the leading endbr64 with a nop if the function's address wasn't
taken.
For evaluation, I built the mold executable itself both with and without
this option. Before using the `-z rewrite-endbr` option, the mold
executable contained 25,994 endbr64 instructions. With the option, the
number becomes 18,035, a 30% reduction.
The new option is exprerimental; we may remove it in a future versions of
the mold linker.
For example, when the leader's instruction is removed and a follower is right
next to it, the follower's relocation can point to the follower's address
itself. In this case the leader's relocation may lie before or after the
follower, so just search for both.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
I made a fair amount of effort to try to support MIPS, but it turned out
that it is much harder than expected. I punted it instead of making
further efforts.
The problem is the MIPS ABI is hostile to the linker in the modern
environment. MIPS object files are still compiled for the small code
model in which GOT entries and data in the small data area are expected
to be accessible with a single machine instruction with a 16-bit
displacement. In other words, .got/.sdata/.sbss are expected to be
smaller than 64 KiB. This might have been a reasonable assumption in the
90s, but it's not suitable for modern applications that can be 1000x
larger than the binaries in the 90s.
MIPS requires the linker to implement tons of workarounds for its legacy
ABI assumptions. Our incomplete MIPS support can build binaries that
pass all our unit tests. However, it needed more effort to support
real-world programs that are larger than our test cases.
At this point, I don't think it is productive to implement workarounds
for the old ABI that is stuck in the 90s. It is honestly annoying to
think about workarounds for the code that is intentionally compiled to
be hostile to the linker. The situation is unfortunate, but if the
Open Source community is still serious about MIPS, they should improve
the ABI and the compiler instead of asking us to implement the legacy
ABI.
Closes https://github.com/rui314/mold/issues/1040
Quote from Arm Cortex-A75 Software Optimization Guide
(PJDOC-466751330-205) p.59:
Consider aligning subroutine entry points and branch targets to
16-byte boundaries, within the bounds of the code-density requirements
of the program. This ensures that the subsequent fetch can maximize
bandwidth following the taken branch by bringing in all useful
instructions.
`CMakeLists.txt` declares a minimum CMake dependency on 3.14.
```
cmake_minimum_required(VERSION 3.13)
```
But the `--install` switch is only available since CMake 3.15, see
<https://stackoverflow.com/a/56457739>.
This commit updates the installation instructions in `README.md` so that
they work with CMake 3.14.
If an as-needed DSO is referenced only by other DSOs and not by
the output file we are creating, we won't mark it as "needed".
Fixes https://github.com/rui314/mold/issues/1036
Although we do not support TLSDESC on any target on which
ctx.tls_begin != ctx.dtp_addr, my understanding is that the origin
of the TLSDESC base relocation is tls_begin.
Object files have to be compiled with `-fPIE` or `-fPIC` for a
position-independent executable, and such object files shouldn't
contain relocations that directly refers to data objects without
GOT.
ARM64's crt1.o may refer to `main` with the following four instructions
instead of with the usual `R_AARCH64_ABS64` relocation:
18: d2e00000 movz x0, #0x0, lsl #48
18: R_AARCH64_MOVW_UABS_G3 main
1c: f2c00000 movk x0, #0x0, lsl #32
1c: R_AARCH64_MOVW_UABS_G2_NC main
20: f2a00000 movk x0, #0x0, lsl #16
20: R_AARCH64_MOVW_UABS_G1_NC main
24: f2800000 movk x0, #0x0
24: R_AARCH64_MOVW_UABS_G0_NC main
28: d2e00003 movz x3, #0x0, lsl #48
So we need to create a PLT if a symbol is referred to by this way.
Fixes https://github.com/rui314/mold/issues/1074
Although incomplete, this implementation is capable of passing the
following tests:
TRIPLE=mips64el-linux-gnuabi64 bash -x ../test/elf/hello-dynamic.sh
TRIPLE=mips64-linux-gnuabi64 bash -x ../test/elf/hello-dynamic.sh
Undefined versioned symbols are handled specially; they are resolved
at the very end of name resolution stage. When they are resolved, we
need to make sure that they are marked as imported symbols.
Fixes https://github.com/rui314/mold/issues/1057
Convenient if you have configured to use mold for a particular project but want
to test a new local build.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
open() can fail with transient reasons, such as running out of file descriptor
limit. Previously, this was treated the same as file not being found, which
caused confusing error messages [1].
With this change anything but ENOENT will be treated as a fatal error. This will
also include e.g. permission errors, but if there's something within the search
path that is not accessible, it's likely better to tell the user instead of
silently skipping it.
[1]: https://github.com/rui314/mold/issues/1026
Signed-off-by: Tatsuyuki Ishi <[email protected]>
STT_GNU_IFUNC is significant only for exported symbols. Setting
non-exported symbol type to STT_GNU_IFUNC actually causes an issue
if the symbol is used as a canonical PLT because the runtime would
try to run the canonical PLT as an IFUNC.
Fixes https://github.com/rui314/mold/issues/1028
I made this change by asking GPT-4-based ChatGPT to improve this
document with an additional note that this document was written by a
non-native English speaker and may have wrong or unnatural phrases.
Fixes the following error:
/elf/thunks.cc:81:32: warning: enum constant in boolean context [-Wint-in-bool-context]
return ty == R_PPC64_REL24 || R_PPC64_REL24_NOTOC;
Signed-off-by: Martin Liska <[email protected]>
Handle .eh_frame in a similar way as mergeable sections.
This seems to be required for GCC CRT compiled with LTO.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
When LTO is enabled for CRT it seems symbols like __EH_FRAME_BEGIN__.lto_priv.0
can be created. Treat it as the same as the non-LTO variant.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Previously, we clear liveness bits for all input files after compiling
IR object files to real object files so that we can do name resolution
completely from scratch. However, that can result in inconsistent name
resolution results before and after LTO.
Consider a weak defined symbol X in an object file. A weak undef doesn't
pull files out of an archive file. However, if symbol X is transformed
to an undefined symbol as a result of LTO, it could pull out a file from
an archive. That can have cascading effects and result in a link failure.
With this fix, all object files that are alive at the time when LTO kicks
in are guaranteed to be kept after LTO.
Fixes https://github.com/rui314/mold/issues/991
Previously, we failed to report an undefined error if we have two
undefined symbols, a strong and a weak one, for the same symbol.
It is an undefined symbol error if an undefined symbol is resolved
to a weak undefined symbol.
Fixes https://github.com/rui314/mold/issues/967
Ideally we wanted to use __builtin_assume() or [[assume]], but the former
is available only in clang and the latter is in C++23.
Fixes https://github.com/rui314/mold/issues/966
Previously, we created section symbols only for memory-allocated secitons.
That resulted in symbols with invalid section indices for the --relocatable
output.
https://github.com/rui314/mold/issues/957
Since the maximum size of RangeExtensionThunk is 100 KiB, it can't contain
too many entries, so the contents is addressable with a 16-bit value.
We don't create more than 32768 range extension thunks (unless the output
is hundreds gibibytes in size), so we can also use i16 to specify the
index of RangeExtensionThunk.
We used to have `--print-dependencies` and `--print-dependencies=full`
options. I think this distinction is necesssary. Now, `=full` is renamed
`--print-dependencies`.
These aren't bug, but I decided to repeat the same code instead of
adding [[fallthrough]] because the code duplication is very small.
Fixes https://github.com/rui314/mold/issues/952
We used to try to avoid using identifiers such as S, A or P more than
once because they were defined as macros expaneded to function calls.
Now they are just variables, so we can use them as many times as we
want without any performance penalty.
Unknown relocations will be reported by scan_relocations(). We don't
want to execute unreachable() statement in get_addend() because it
triggers undefined behavior.
https://github.com/rui314/mold/issues/947
It looks like R_ARM_PLT32 can be applied to non-BL/non-BLX instructions,
so we can't handle it as an alias for R_ARM_CALL.
https://github.com/rui314/mold/issues/934
This reverts commit cbd88ed3f3.
It was a nice abstraction but wasn't worth its complexity unless we
use it in various places. The original simple code is more in line
with other parts of mold.
Fixes https://github.com/rui314/mold/issues/946
We used to use C macros as a poor-man's way to inline Symbol::get_addr(),
but it looks like inlining that member function isn't an overall win.
This change removes `inline` from that member function and depends on the
compiler's optimizations to optimize function calls.
We were inconsistent as to when to clear existing values when applying
relocations. mold was broken from the point of view that bits must be
cleared before applying relcoations. But at the same time, we had code
to clear bits for some types of relocations.
This patch removes all bit clear code for the sake of simplicity.
According to the ARM psABI document, R_ARM_PLT32 is deprecated.
It looks like old compilers emit it for function calls.
Fixes https://github.com/rui314/mold/issues/934
Right now, mold linker does not work with -fno-use-linker-plugin
and thus use assembly for GCC FAT LTO objects. I noticed that
when running GCC test-suite with mold.
Fixes: 804b843983
Signed-off-by: Martin Liska <[email protected]>
Linking symbols with differing types will almost always lead to a crash; warn to
make it easier for the user to figure out the cause.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
This is a tricky case, but if you initialize a global variable with a
pointer to an ifunc function like this:
int bar() __attribute__((ifunc("resolve_bar")));
void *bar2 = bar;
then we need to emit two dynamic relocations, one for `bar()` and the other
for `bar2`. This results in calling `resolve_bar` twice at runtime, but
there's no other way to initialize the function and the variable correctly.
Fixes https://github.com/rui314/mold/issues/915
In the current version of Docker image, OpenSSL libraries are installed
to `/usr/local/lib64`. It is not present in the default dynamic linker
search path, and thus results in the following error when libcrypto is
not statically-linked:
mold: error while loading shared libraries: libcrypto.so.3: cannot
open shared object file: No such file or directory
Fix that by overriding `libdir`, as suggested in
https://github.com/openssl/openssl/blob/master/INSTALL.md#libdir. Also,
run `ldconfig` to update dynamic linker cache.
Signed-off-by: Ruoyu Zhong <[email protected]>
A symbol with `STT_SECTION` doesn't have name (i.e. its `st_name` is zero.)
If such symbol is used as a comdat group name, we need to use a section name
instead of a symbol name as a group name.
Similarly to x86_64, use int3 (0xcc) as padding at the end of plt
and pltgot entries in order to increase security.
Signed-off-by: Martin Liska <[email protected]>
Recent versions of Xcode started creating `_objc_msgSend$foo` symbols,
and we need to synthesize the symbols and place them into `__objc_stubs`
section.
Add an undefined symbol to keep a reference to the defsym target. This prevents
elimination by e.g. LTO or gc-sections. A test is added for the case of LTO
dead-code elimination.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
In preparation for introducing undefined symbols that references external object
files (and should not get the output section overridden).
Signed-off-by: Tatsuyuki Ishi <[email protected]>
SHF_LINK_ORDER bit doesn't matter in an executable, but it looks like
the `strip` command in binutils 2.35 or earlier on ARM32 complains about
`.ARM.exidx` if we do not preserve that bit.
Fixes https://github.com/rui314/mold/issues/889
We used to create copy relocations if we are creating a non-PIC executable
and there's a direct reference to imported data. That works for most
programs but not for GHC (Glasgow Haskell Compiler). GHC places function
machine code and its supplimental data next to each other in the .text
section. If we create a copy relocation for such function, the resulting
executable won't work because (1) copy-relocated data is not executable
and (2) it may separate the function code from its supplemental data.
In this patch, I made a change so that mold creates dynamic relocations
instead of copy relocations if possible.
TLS chunks alignments are special: in addition to having their virtual
addresses aligned, they also have to be aligned when the region of
tls_begin is copied to a new thread's storage area. In other words, their
offset against tls_begin also has to be aligned.
A good way to achieve this is to take the largest alignment requirement of
all TLS sections and make tls_begin also aligned to that.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
FAT LTO objects are objects that contain both native assembly
and LTO bytecode. Identify such files as GCC_LTO_OBJ.
Signed-off-by: Martin Liska <[email protected]>
Previously, we create output sections when input sections are instantiated.
That is not ideal because input sections may be removed, and if that's the
case, any work that has done for the removed section is wasted.
This is an initial patch to reimplement --relocatable. Unlike the previous
implementation, the new one aims to be on par with GNU ld in terms of the
behavior. Previously, we didn't for example merge input sections at all.
Now we do it in the new implementation.
The previous implementation was slow. We also want to fix it in the new one.
The new --relocation feature is not complete yet; there are many rough edges.
But I think this patch is good enough to be submitted.
This work is funded by Mercury (https://mercury.com).
As documented by CMake [^1], prior to CMake 3.13, entries set by
`option()` can override a non-cached old value. The `CMakeLists.txt` in
the bundled mimalloc specifies a minimum CMake version of 3.0, so that
old behaviour is expected. That means no matter whatever value of
`MI_BUILD_STATIC` we set in `mold_add_mimalloc` does not really take
effect (this can be seen by adding some debug messages). That didn't
trouble us because it's on by default anyway.
While the documented solution is to set `CMAKE_POLICY_DEFAULT_CMP0077`
to `NEW`, we could actually also work around this by making them cache
variables. This is fine and valid because their values are not meant to
be changed anyway. (And this workaround is already being used in
`mold_add_tbb`, so by doing this, we are also eliminating some
inconcistency.)
Fixes#874.
[^1]: See `cmake --help-policy CMP0077` or
https://cmake.org/cmake/help/latest/policy/CMP0077.html
Signed-off-by: Zhong Ruoyu <[email protected]>
The square-bracket operator of `std::span` has undefined behaviour for
out-of-bounds element accesses. Resorting to iterators yields defined
behaviour.
This issue (originally described in #298) had been fixed in the past by
commit 03ba8f9325, but it has since
resurfaced with commit 193c245781.
Signed-off-by: Christoph Erhardt <[email protected]>
This makes .gnu.note.property handling generic instead of hardcoded against the
GNU_PROPERTY_X86_FEATURE_1_AND value.
The behavior is based on specification inside GNU gold header comments;
unfortunately a formal document does not exist yet and the comments seem to be
the best reference that can be found.
The support for the actual properties in wild seems scarce; neither gcc nor
clang emits the correct property even when passed -march=x86-64-v3 and using
__builtin_popcnt, for example. Therefore, this does not include a test yet for
the new properties.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Includes value required to handle the "ABI needed" and "ABI used" tags, but
doesn't include the feature values yet (because we don't have a use for it).
Signed-off-by: Tatsuyuki Ishi <[email protected]>
binutils has learned to inject some "x86 ISA needed/used" properties.
Try to disable their emission with -mx86-used-note=no if supported, since
now that mold is gaining support for these properties, they will cause an
mismatch with the expectations.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
This removes the extra slash in the symlink
installation output. It works because both
NEW_ABS and NEW_DIR are absolute paths, and
therefore always begin with a slash.
Signed-off-by: Zhong Ruoyu <[email protected]>
`git pack-refs` (often called by `git gc`) may
move refs from `.git/refs` to
`.git/packed-refs`. If that is the case, a lookup
in `.git/refs` will fail.
Signed-off-by: Zhong Ruoyu <[email protected]>
Earlier entries in a version scripts always get the precedence. Don't let a
non-C++ symbol rule override a preceding C++ symbol rule.
MultiGlob is modified to return the necessary rule index information to the
caller. Since the rule index might not always be contiguous within a
MultiGlob instance (e.g. interleaving ordinary/C++ rules), the meaning of
MultiGlob's `val` is changed so that the minimum `val` itself is returned,
instead of the `val` with minimum index (the earliest added one).
MultiGlob is also used for the macOS backend, but since it does not care
about order yet the code is left as-is.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
We can create peculiar executables with --section-order, and some ELF
loaders don't like some of them. Since the flag is intended to be used
for embedded/kernel programming, we don't need to verify that the
executables work on regular Linux macines.
Fixes https://github.com/rui314/mold/issues/838
We are using OpenSSL only to compute SHA-256 hashes, so we are unaffeted
by CVE-2022-3786 and CVE-2022-3602. But I think we still want to use the
newer version of OpenSSL to avoid unnecessary confusion.
Currently, `CMAKE_INSTALL_FULL_{LIBEXEC,BIN,MAN}DIR`
are used for symlink creation. The problem with
that is it only works when the prefix is not
overridden by `cmake --install <build-dir> --prefix <prefix>`,
because their values are evaluated and hard-coded
into `cmake_install.cmake` during configuration
time, rather than installation time.
While it would be nice if we can get their
overridden values during installation, only
`CMAKE_INSTALL_PREFIX` reflects the overriden
value. (See "INSTALL A PROJECT", cmake(1)).
Therefore, the logic for symlink creation is
rewritten and extracted into a function named
`mold_install_symlink`. Now only `CMAKE_INSTALL_PREFIX`
is used during installation.
A new problem with this change is, if environment
variable `DESTDIR` is not set and `CMAKE_INSTALL_PREFIX`
is set to a relative path (which is perfectly
valid), a slash `/` would be incorrectly
prepended. To avoid that, and maintain
consistency with CMake's behaviour, the install
prefix is first turned into absolute path, stored
in `PREFIX_ABS`.
By the way, it seems okay to use the
`MAKE_DIRECTORY` and `CREATE_LINK` subcommands
under command `file`. So, it shouldn't be needed
to invoke a subprocess.
Signed-off-by: Zhong Ruoyu <[email protected]>
We can already print them, but a counter is more handy when the
executable is large and dumping everything would be too much.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
This isn't perf intensive at all but sweeping through the sections seems
to be the more obvious way compared to going through the symbol
indirections.
Also, reword the comments and timing name to better reflect what it's
doing.
FWIW, it's slightly (5ms) faster.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
A node converges if its descendants contains no cycles and its hash has reached
all its descendants. Previously we checked for convergence on each iteration by
comparing hashes, but this could be tracked more cheaply through a separate
bitset.
This improves cache efficiency and results in a ~50ms speed up for Chromium out
of 310ms for the ICF pass.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
It looks like the runtime doesn't care the non-loadable segments'
p_addr values, but `strip` does. `strip` corrupts an executable if
no value is set to p_vaddr.
Fixes https://github.com/rui314/mold/issues/839
This is an experimental flag and may be deleted in the future.
If --start-stop is given, mold creates __start_/__stop_ symbols for
sections whose names are not in C identifier style.
With toolchains using a relative sysroot, like crosstool-ng, gcc/clang will call the linker
with something like "--sysroot=/path/bin/../machine/sysroot".
The is_in_sysroot detection wasn't working in this case.
Since to_abs_path() uses lexically_normal() for relative paths, it seems consistent to do
the same for absolute paths instead of modifying is_in_sysroot().
They should inherit the original type instead of using a value from the wrong
enum (which showed up as R_X86_64_GOT32).
Signed-off-by: Tatsuyuki Ishi <[email protected]>
When using ld64.mold to link clang for Mach-O, most of the time was
spent in the first call to find_subsection() from
parse_compact_unwind(). Changing its linear search to a binary search
cut an 18-second link time down to about 3 seconds.
Signed-off-by: James Widman <[email protected]>
We only need the RMW to be atomic and doesn't need the ordering guarantee wrt
other memory locations.
Might make ARM a little faster (no machine code change for x86).
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Atomic RMW operations can take hundreds of cycles and tends to be massively
slower than a fence-free alternative.
Add a fast_mark function that optimistically tests if the node is already
visited first, which allows avoiding the fence penalty if we can early exit.
When testing on Chromium, this roughly improved the associated pass's runtime
by 20--30%.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
We've long had a hack to de-prioritize GNU_UNIQUE symbols, due to an edge case
where these symbols could get higher resolution priority yet eliminated in the
later COMDAT elimination stage. But since GNU_UNIQUE symbols were supposed to
have a resolution as strong as GLOBAL symbols, it created unsoundness in the
resolution and could have cause false duplicate symbol errors in later stages.
The root cause is that COMDAT elimination, unlike ICF and SHF_MERGE, removes
symbols from the candidate pool and can actually affect resolution result. Hence
we ought to do the elimination before the final resolution.
Doing so requires fully wiping the resolution instead of just the ones from
eliminated archive members. This has a performance hit that we need to keep an
eye on.
On another note this wiping of resolution is actually justifiable. The old
algorithm did not handle the case of an archive member overriding a DSO symbol.
So wiping is the correct way even in absence of COMDAT elimination.
One caveat is that currently the symbol resolution stage doesn't actually care
about the is_alive flag which is how COMDAT symbols are killed. There are two
other users of this flag: mergeable sections, and eh_frame. The eh_frame section
is already handled with special logic, and we can treat it as if it had no
symbols to resolve. Mergeable sections needs a bit more careful handling, but a
good way is to just leave them unmerged and update the references in the same
later pass where merge happens. This has been done in a prior commit.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
This pass is rather different in that it runs the resolve pass with lower
priority for archive symbols in order to determine extraction. Split it out to
better convey its difference.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
We can skip the is_alive condition by doing the compaction beforehand.
This also allows splitting this function into two phases clearly which will
happen later.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Make sure clear_symbols() are called on IR object files too, so that we'll never
have references to symbols inside IR object files after LTO. Can't really think
of an example that causes problem, but for sanity.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
When the section-header index has the escape value `SHN_XINDEX`, the
actual index must be looked up in the separate `SHT_SYMTAB_SHNDX` table.
Trying to use `SHN_XINDEX` (= 0xffff) as an index results in an
out-of-bounds read. The error can be observed when running the
`x86_64_many-sections.sh` test on RHEL 8 or 9 (but not on Fedora,
because there the assembler doesn't emit section symbols).
Instead of using `st_shndx` directly, call the pre-existing helper
method `get_shndx()` to get the correct behaviour.
Signed-off-by: Christoph Erhardt <[email protected]>
Even if we always enable assert(), we want code to be able to compile
with assert() being expanded to a null statement. I.e., we should not
write code that has side effect in assert().
In order to add a test case for it, I added a cmake option to force
disable assert().
Our assertions are cheap, and the cost of branch instructions that
are never taken is almost free thanks to hardware branch prediction.
So I don't think it's worth to disable it for release builds.
We set a value to .ARM.exidx's sh_shlink to appease GNU binutil's
strip command (this value is not used by runtime), but even strip
doesn't care what value is set! We set a wrong value by accident.
Fixes https://github.com/rui314/mold/issues/804
We've been treating STB_GNU_UNIQUE symbols as if they were weak.
The rationale of doing is this:
1. GCC sometimes creates GNU-unique symbols instead of weak ones
for comdats, and
2. after COMDAT de-duplication, we used to report a duplicate symbol
error for GNU-unique symbols
However, (2) is no longer the case because we do not report a symbol
duplication error if its section is dead.
I'm not sure if this new logic will work for all programs, but I want
to give it a shot.
https://github.com/rui314/mold/issues/524
GNU binutil's strip command doesn't like an .ARM.exidx section with
sh_link set to 0. arm-linux-gnueabihf-strip actually crashes on my
machine when the command is run on such a file.
https://github.com/rui314/mold/issues/801
536e0e7d ("[elf] Align .symtab's ELF attributes with .dynsym's.") fixed the
issue of .dynsym and .symtab disagreeing with each other, but in the
process introduced change to the symtab index. --emit-relocs was assuming
the old assignment logic, which caused mismatches as soon as any
global-to-local demotion happened.
Fix this to use the demotion-aware assignment logic by directly filling in
the indices as we assign them to symtab, and by making get_output_sym_idx
to test global/local using the new is_local() helper.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
I don't know why GCC sometimes creates a PC32 relocation instead of
PLT32 after a TLS_GD/TLS_LDM. I believe it's strictly speaking a
violation of the psABI. But we need to handle such input.
Fixes https://github.com/rui314/mold/issues/794
This matches what was done in `Makefile` in #561, but the check was extended
in the CMake port.
It builds fine without `-latomic` on Mageia 9 armv7hl nodes, fails with
explicit `-latomic`.
Signed-off-by: Rémi Verschelde <[email protected]>
Previously, an undefined symbol in a DSO can mark other DSO as "needed".
But that lead to mark more DSOs needed as necessary. It is also a bit
counter-intuitive.
The new behavior is still slightly different from GNU ld, but I believe
it's now compatible with LLVM lld.
Fixes https://github.com/rui314/mold/issues/786
As stated in the comment, have at least one permutation that checks for missing
(implicit) header includes.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Since we're having lots of arch-generic permutations, headers seems to be a good
place where potential perf improvement are possible.
The feature is gated against CMake 3.16.0 or later, which is when it was
implemented.
Measured on 3990X, with this change it takes:
ninja 1166.22s user 34.45s system 5378% cpu 22.322 total
While before it took:
ninja 1776.81s user 51.30s system 7172% cpu 25.489 total
So a 10% improvement for workstation users and even more if you don't.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
We have been setting the symbol value and size correctly, but the SHNDX was
erroneously set to UND, potentially causing undefined symbol errors. Fix this by
forwarding the appropriate value from the `leader`.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
It looks like we don't have to conservatively set GOT[0] to .dynamic
on s390x. glibc's -static-pie depends on GOT[0], so we need to set for
it, though.
These relocations are defined as follows
R_SPARC_GOTDATA_OP_HIX22 (G >> 10) ^ (G >> 31)
R_SPARC_GOTDATA_OP_LOX10 (G & 0x3ff) | ((G >> 31) & 0x1c00)
where G is an offset into .got. Since .got is much smaller than 4 GiB,
(G >> 31) is always zero, so we can ignore that part.
https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter6-24/index.html
Fixes:
macho/input-files.cc:310:31: warning: missing initializer for member ‘mold::macho::Subsection<mold::macho::ARM64>::replacer’ [-Wmissing-field-initializers]
elf/mold-wrapper.c:68:15: warning: passing argument 1 of ‘debug_print’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
Signed-off-by: Martin Liska <[email protected]>
We should only override the default export behavior in executable if the default
version was actually overridden by a linker script (i.e. local: *;). Other
options, such as --dynamic-list and --export-dynamic-symbol[-list], doesn't
actually change this default, and should not be considered for this override.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Since around 2015, IBM seems to have been encouraging their customers to
use PowerPC systems in little-endian mode. They ratified the little-
endian ABI for PPC64. Since it was completely a binary-compatibility-
breaking change anyway, they didn't only change the endianness but made a
few improvements to the ABI they have been wanting to make. So the new ABI
was born.
The new ABI is called the ELFv2 ABI. The original, big-endian-only one
is retrospectively called ELFv1. Technically, the new ABI supports both
little endiannesses. but effectively all systems that employ ELFv2 are
using the processor in the little-endian mode.
There are still many PowerPC systems that use the original ELF ABI in the
little-endian mode for binary compatibility. This commit is for such systems.
We already support ELFv2. Look at arch-ppc64v2.cc.
Currently, "73% tests passed, 63 tests failed out of 234" for the ppc64v1
target according to ctest.
As explained in the "A classic way to use mold" section, the latest GCC releases support `mold` out of the box. Rust can take advantage of this to use `mold` too, without going through a system-wide `clang` linker.
I've just tested this on my Linux workstation that runs Debian unstable.
glibc for ARM64 prior to August 2021 arguably wrongly assumes that
the GOT first entry contains the address of the .dynamic section.
That's been removed in the following commit, but without satisfying
that assumption, mold can't create working static position-independent
execuables for ARM64.
https://sourceware.org/git/?p=glibc.git;h=43d06ed218fc8be58987bdfd00e21e5720f0b862
They are failing only on GitHub Actions. I believe they don't work
with older versions of glibc. Until we fix them, I want to disable
them so that the tests are green.
The implementation is far from complete, but mold/s390 is already able
to dynamically link a "Hello World" program for s390 which can
successfully run on qemu-s390x.
If a symbol has both PLT and GOT entries, we used to create its PLT
entry in .plt.got so that the runtime needs to look up the symbol
exactly once. This optimization however doesn't seem to be useful
because the number of such symbols is usually very small (<100 for
a large program). So I don't think its worth its complexity.
.gnu.warning* section may contain strings referenced by other sections,
so we can't discard them unconditionally. In this commit, we simply
keep all .gnu.warning* sections.
This allows CTest to differentiate between tests that were executed
successfully and tests that were skipped.
Signed-off-by: Christoph Erhardt <[email protected]>
We used to extend just a load segment containing RELRO sections.
strip command shrinks such segment so that it fits its contents.
So we need a dummy section for padding.
https://github.com/rui314/mold/issues/732
`readelf --symbols` print out auxiliary information after a symbol name
for PPC64, so something like `foo$` didn't match.
7: 0000000000000000 80 FUNC GLOBAL DEFAULT 3 main [<localentry>: 8]
8: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND .TOC.
9: 0000000000000000 72 FUNC GLOBAL DEFAULT 11 foo [<localentry>: 8]
10: 0000000000000000 40 FUNC GLOBAL DEFAULT 19 bar
Fixes https://github.com/rui314/mold/issues/739
They are both read-only, so by placing them next to each other, we can
reduce the number of the load segments by one, which translates to one
less mmap(2) at runtime.
This commit reverts the following commits:
- 3d33349691 [ELF] Fix -max-page-size
- 14b2ba3b74 Refactor
- 41c762b6c5 Update comments
- d22e85f345 [ELF] Save one memory page for RELRO
- 2941d75c71 [ELF] Do not page-align loadable segments
- a2552b6fd1 Refactor
- 919f58dc5d Fix CI
- ef6e6ecdf4 Refactor
- 9c7b95f108 [ELF] Do not page-align RELRO and TLS segments
I'll revert these changes because they caused a regression on systems
with large page size. Even though I believe most users are not
affected, it's a critical bug as mold creates completely unusable
output files for certain systems. In order to release 1.5.1, I'll
revert all of them.
This fixes the following error when Clang 15 is installed on the system:
> mold: error: out/test/elf/x86_64/run-clang/a.o:(.text):
> R_X86_64_32 relocation at offset 0x5 against symbol `.rodata' can not
> be used; recompile with -fPIC
The error occurs because Clang 15 assumes PIE to be enabled by default:
https://releases.llvm.org/15.0.0/tools/clang/docs/ReleaseNotes.html#build-system-changes
Attempting to produce a position-independent executable from an object
file that was created by `cc` without `-fPIE` caused the linker to bail
out.
Signed-off-by: Christoph Erhardt <[email protected]>
Looks like Intel C/C++ compiler emits this symbol in .eh_frame.
I don't excatly know how this symbol is being used, but it looks like
this symbol is supposed to refer the beginning of the output .eh_frame.
Fixes https://github.com/rui314/mold/issues/685
Previously, we align each loadable segment and the beginning of
readable-writable non-RELRO segment to page boundaries. That's one
posible layout, but it made too many holes in files that resulted
in output file bloat.
That bloat is most visible on targets supporting large pages.
We conservatively link output files for the largest possible page
size so that the output will run both on large pages and usual small
pages. As an example, we use 64 KiB as a page size for ARM64.
So we wasted up to 64 KiB for each loadable segment. A "hello world"
program for exapmle became almost 200 KiB on ARM64 because of that
reason.
This commit changes the file layout. Loadable segments are no longer
aligned to page boundaries. Loadable segments are still placed into
different memory pages. A page at a boundary of two loadable segments
are doubly mapped to memory.
This change reduces output file size. It is most noticeable when an
output is small -- a "hello world" on ARM64 is now smaller than 10
KiB now.
Since the actual writability is controlled by the W bit of the LOAD
segments, I don't think it actually matters. But in the spirit, TLS
segment contains the initial TLS image and should not be writable.
CMake 3.13 should be reasonably old enough. Ubuntu 20.04 includes
CMake 3.16.3. I wanted to support Ubuntu 18.04's CMake, but that was
3.10.2, and that's too old.
Almost all functions and data types are template in mold, which are
parameterized to target type (e.g. X86_64 or ARM32). I'm generally
happy with that design, but there's one drawback; as we add more
targets, compilation gets slower.
Now we support more than 10 targets, so the compiler has to do 10x
more work than it originall did. As a result, compiling output-chunks.cc
(one of our largest file) took more than 30 seconds to compile on a
Threadripper machine. I hasitated to add a support for a new target
because of this problem. We needed to fix it.
This commit tweaks the build system configs so that the build system
generates bunch of intermediate .cc files. Each generated .cc file
instantiates an original .cc file for one target.
The total amount of required computation doesn't change by this hack,
but now we can parallelize the compilation step. That works well on a
modern multi-core machine.
I generally don't like to tweak build system to workaround a tool's
issue (that's why I'm creating mold in the first place), but it looks
like there's no way to speed up compilation other than this. Or,
maybe we can write a faster C++ compiler someday, but that's another
topic.
The original PPC64 psABI was big-endian only which is retrospectively
called the ELF v1 ABI. Around 2016, IBM decided to push little-endian
use of PowerPC platform and ratified a new psABI which is called the
ELF v2 ABI.
Changing the endianness inevitably breaks ABI compatibility, so IBM
took that chance to clean up the ABI. So the difference between v1 and
v2 are not just endianness.
However, v2 isn't technically little-endian only. You can still create
an ELFv2-based big-endian system. Such systems are not popular though.
In many systems, the original ELFv1 big-endian system is called
"ppc64" and the v2 little-endian system is called "ppc64le". But these
names are not very accurate. I think ppc64v1 and ppc64v2 (or ppc64v2le
and ppc64v2be) are more accurate.
Bitfields are placed in an address-increasing order on both little
and big-endian hosts. Therefore, the following struct has the same
layout on both endiannesses.
struct {
uint32_t x : 8;
uint32_t y : 16;
}
The address of `x` is smaller than `y`, though you can't take an
address of a bitfield using the `&` operator in C.
However, if two bitfields are placed the same byte, they are placed in
a reverse order. In LE, bitfields are placed from LSB to MSB, while in
BE, they are placed from MSB to LSB. Therefore, members something like
this
struct {
uint32_t x : 4;
uint32_t y : 4;
}
needs to be swapped.
__tls_get_addr is not available in statically-linked executables,
so we have been relaxing all TLSGD and TLSLD relocations for static
executables. However, I noticed that it's much easier to provide a
replacement function for __tls_get_addr instead of implementing all
TLS relaxations.
With this change, all mold's unit tests pass on qemu-sparc64.
Previously, a relocation is associated either to a symbol or a section
fragment. Now, we synthesize a symbol for each unnamed piece of section
fragment and associate it to a relocation.
A symbol can belong to an input section, an output section or a section
fragment. They are mutually exclusive, and their data structures are
aligned to at least 4 bytes boundaries. So we can use a tagged pointer
to store all of them in a single pointer-size object.
GCC prints out bunch of the following warnings when compiling mold.
```
macho/input-files.cc:717:11: warning: 'void* memset(void*, int, size_t)'
clearing an object of non-trivial type 'struct mold::macho::MachSection';
use assignment or value-initialization instead [-Wclass-memaccess]
717 | memset(hdr, 0, sizeof(*hdr));
| ~~~~~~^~~~~~~~~~~~~~~~~~~~~~
```
This commit suppresses it by making our classes trivial.
https://github.com/rui314/mold/issues/708
Previously, TLSLD relocation on i386/x86-64 produced different values
than it normally does if it's relaxed. If relaxed, it's evaluated to
TP, which is the end address of the TLS block. If not relaxed, it's
evaluated to the beginning of the TLS block.
As a result, we needed to adjust subsequent DTPOFF relocations so that
it is based on the end of the TLS block only when the corresponding
symbol was relaxed. This is very tricky.
I believe the psABI TLS spec specifies this way because they couldn't
find a replacement instruction sequence that is equal to or shorter
then the replacing instructions. `mov %fs:0, %rax` is 9 bytes long,
so it barely fits the location where a TLSLD refers to.
I found that `xor %eax, %eax; mov %fs(%rax), %rax` is shorter than
`mov %fs:0, %rax` while it yields the same value. The two instructions
are 5 bytes in total. By saving 4 bytes, we can now add another `add`
instruction to adjust the resulting value, so that the result is always
relative to the beginning of the TLS block.
On ARM, calling an remaining weak undefined symbol is a NOP. But
if such symbol was promoted to a dynamic symbol, we need to execute
that call instruction instead of converting to a NOP because it may
be resolved to a defined symbol at runtime.
Fixes https://github.com/rui314/mold/issues/660
glibc started printing out the following warning message on process
startup, starting from glibc 2.36:
warning: direct reference to protected function `baz' in
`out/test/elf/x86_64/protected/b.so' may break pointer equality
It does so if it finds there's a canonical PLT against a protected
symbol. The warning message itself makes sense -- there's no way to
create a canonical PLT against a protected symbol while keeping
pointer equality, and you should recompile object files with `-fPIC`
to suppress this warning.
However, in this test, we intentionally create a canonical PLT against
a protected symbol, so we just want to silence it.
Fixes https://github.com/rui314/mold/issues/689
We saw a significant performance improvement with this commit. Here
is before and after numbers when cross-building mold for RV32 on a
simulated 16-core machine:
$ time ./mold.old @rsp
real 0m45.216s
user 0m0.016s
sys 0m0.000s
$ time ./mold.new @rsp
real 0m0.240s
user 0m0.014s
sys 0m0.003s
$ ls -lh mold
-rwxrwxr-x 1 ruiu ruiu 152M Sep 4 17:16 mold
For RISC-V, DTPOFF is computed 0x800 off from the start of each TLS block
to maximize the accessible range for memory access instructions with
signed 12-bit immediate. DTPMOD is usually computed by the dynamic loader,
but when we do for static binaries, we need to subtract 0x800 to offset
the offset.
https://github.com/rui314/mold/issues/461
This reverts commit e65cc7feea because
I don't think this is a correct fix.
We can't emit a R_RISCV_32 dynamic relocation for R_RISCV_HI20
relocation. If we do, the dynamic loader will override an entire 32
bit word with an address of a specified symbol. HI20 is expected to
set a high 20 bits as an instruction operand, so they are not
compatible.
https://github.com/rui314/mold/pull/668
I was not correct as the 'sorry, unimplemented: Thumb-1 'hard-float' VFP ABI
really comes late in target register allocator. Thus one needs to
assembly a function.
Fixes: #655
Signed-off-by: Martin Liska <[email protected]>
I don't think PIE uses R_AARCH64_ADR_PREL_PG_HI21 relocation because
in PIE, we need to use R_AARCH64_CALL26 or R_AARCH64_JUMP26 for branches
and use GOT to take an address of a global object.
- PC64 relocations are not representable using DYNREL because
DYNREL is for an absolute address
- PC-relative relocations should be able to refer PLT entries
in the same ELF module
Fixes#550.
In the Arm32 [spec][spec], R_ARM_GOT_PREL is defined as follows:
R_ARM_GOT_PREL: GOT(S) + A – P
Where:
> GOT(S) is the address of the GOT entry for the symbol S.
If we look at the code a bit, notice that G is actually the _offset_
of S into the GOT, not the symbol's address in GOT. This patch makes
sure that the relocation is computed using the GOT address of the
symbol, thereby fixing the mentioned issue.
[spec]: https://github.com/ARM-software/abi-aa/blob/60a8eb8c55e999d74dac5e368fc9d7e36e38dda4/aaelf32/aaelf32.rst#5612relocation-types
Signed-off-by: Robert Bartlensky <[email protected]>
If a R_ARM_CALL refers an ARM instruction that jumps to Thumb, we
need to rewrite an instruction to BLX. We previously didn't do that.
Fixes https://github.com/rui314/mold/issues/442
The following warnings are seen:
Testing pltgot ... /usr/lib64/gcc/x86_64-suse-linux/12/../../../../x86_64-suse-linux/bin/ld: warning: /tmp/ccpkwmmy.o: missing .note.GNU-stack section implies executable stack
/usr/lib64/gcc/x86_64-suse-linux/12/../../../../x86_64-suse-linux/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
Testing reloc ... /usr/lib64/gcc/x86_64-suse-linux/12/../../../../x86_64-suse-linux/bin/ld: warning: out/test/elf/x86_64/reloc/a.o: missing .note.GNU-stack section implies executable stack
/usr/lib64/gcc/x86_64-suse-linux/12/../../../../x86_64-suse-linux/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
Signed-off-by: Martin Liska <[email protected]>
The precondition check was supposed to find out whether the compiler
supports `-fcfprotection`, but it always failed complaining about an
undefined reference to `main()`. As a consequence, the test case was
never executed.
Add `-c` to omit the link step in the compiler call.
Signed-off-by: Christoph Erhardt <[email protected]>
Right now, the test prints to the output:
Testing defsym2 ... w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U __cxa_finalize
w __gmon_start__
00000000000010f9 T bar
00000000000010f9 T foo
OK
which is changed to:
Testing defsym2 ... OK
Signed-off-by: Martin Liska <[email protected]>
I was debugging #550, and I noticed a symbol was pointing to the
start of a section, but its shndx was set to SHN_UNDEF. Looking over
the code, I realized that for each section you create a corresponding
output section, but if the input section is mergeable, you also create
a fragment for it whose parent is MergeableSection, which in the end
will be copied into the output binary instead of the output section.
Since the symbol was pointing to the start of a mergeable section, I
realized that it is probably wrong to use the shndx of
`isec->output_section`, because that particular Chunk never actually
makes it to the list of final Chunks for mergeable sections.
Before:
```
$ eu-readelf -s ./target/debug/mold_test | grep _rustc
Num: Value Size Type Bind Vis Ndx Name
77: 000d563c 34 OBJECT LOCAL DEFAULT UNDEF __rustc_debug_gdb_scripts_section__
$ eu-readelf -S ./target/debug/mold_test
[Nr] Name Type Addr Off Size ES Flags Lk Inf Al
...
[22] .debug_gdb_scripts PROGBITS 000d563c 0d563c 000022 0 A 0 0 1
...
```
After:
```
$ eu-readelf -s ./target/debug/mold_test | grep _rustc
Num: Value Size Type Bind Vis Ndx Name
77: 000d563c 34 OBJECT LOCAL DEFAULT 22 __rustc_debug_gdb_scripts_section__
$ eu-readelf -S ./target/debug/mold_test
[Nr] Name Type Addr Off Size ES Flags Lk Inf Al
...
[22] .debug_gdb_scripts PROGBITS 000d563c 0d563c 000022 0 A 0 0 1
...
```
Signed-off-by: Robert Bartlensky <[email protected]>
It seems buggy and causes subtle linker errors. Disable it for now so that
we can focus on getting the essential parts of the linker right.
Fixes https://github.com/rui314/mold/issues/619
These tests were added to the repo, but not the list of tests in the
corresponding CMakeLists. As a result, they are not run in CI when using
CTest.
Signed-off-by: Andrew Kaster <[email protected]>
MSVC has a hard limit of 128 block nesting levels. So you can't write
cascaded "else if"s more than 128. That's a very silly restriction,
but we need to work it around.
Both rust-demangle and xxhash provide usage instructions with include
paths that do not have an extra directory component. This patch fixes
uses of these libraries in the code and avoids including the third-party
directory wholesale.
Signed-off-by: friendlyanon <[email protected]>
Relocation may refer past-the-end location of a section. Therefore,
if section X is [0, 0x1000) and section Y is [0x1000, 0x2000), we
can't determine whether a relocation refers address 0x1000 refers
X or Y. We need to pass a section index.
The `extern "C"` directive in a version script should match a non-C++
mangled name for the sake of compatibility with other linkers. It
caused a regression for libprotobuf.
GCC 11's crtbeginS.o contains `__dso_handle` as a word-size data
which cnotains its own address as a value. Overriding that symbol
programs that depend on the value to crash.
This fix is needed for 7zip.
If a section name is valid as a C identifier (i.e. it doesn't start
with '.' and doesn't contain any punctuators), the linker automatically
creates new symbols by prepending `__start_` and `__stop_` to the
section name.
Previously, we conservatively keep such C identifier sections during
garbage collection. However, since `__start_` and `__stop_` symbols
are hidden symbols, if we do not have `__start_foo` or `__stop_foo`,
we can safely discard section `foo`.
write_symtab feels like we're writing to the input file, which isn't the
case. export_to_symtab conveys the meaning clearer.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
Notably, we previously wrote symbols that have been demoted into STB_LOCAL
as STB_GLOBAL. Fix this by using a logic shared with dynsym to determine
the output attributes.
Also reorder the symbols since the LOCAL ones need to come first.
Found in Mesa test suite.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
parse_dynamic_glob requires the passed string_view to be alive across the
entire linker invocation, so we need to avoid cloning for that.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
According to lld, --dynamic-list "implies -Bsymbolic but does not set
DF_SYMBOLIC" when creating shared objects. Follow suit in this patch.
Note that we don't set DF_SYMBOLIC currently, and arg.Bsymbolic has no
effect on non-shared objects.
Signed-off-by: Tatsuyuki Ishi <[email protected]>
This reverts commit 990b0ac4cd.
This is what the RISC-V psABI says
> The R_RISCV_HI20 refers to an LUI instruction containing the high
> 20-bits to be relocated to an absolute symbol address. The LUI
> instruction is followed by an I-Type instruction (add immediate or
> load) with an R_RISCV_LO12_I relocation or an S-Type instruction
> (store) and an R_RISCV_LO12_S relocation. The addresses for pair of
> relocations are calculated like this:
I read LO12 is guaranteed to always appear after HI20.
`cxa_finalize` takes `__dso_handle` to uniquify identify an ELF module
in memory. Its actual location doesn't matter but needs to be different
for each ELF module.
Fixes https://github.com/rui314/mold/issues/507
This change removes the compact PLT and non-IBT PLT and replaces
them with IBT PLT. The compact PLT wasn't compatible with `-z ibtplt`.
Fixes https://github.com/rui314/mold/issues/581
The command "mold -run foo.ld" can fail when foo.ld is an empty file.
The musl execvp() call fails with "Exec format error" when the script
to be executed is empty. The fix is to create foo.ld with a valid
Unix shebang.
Signed-off-by: Peter Wang <[email protected]>
This fixes a warning produced by GCC 12 related to the initialisation
order of the class members.
For details, see the discussion at
https://github.com/oneapi-src/oneTBB/issues/823. The concern about
potential ABI incompatibility is not relevant for a private bundled
library.
Signed-off-by: Christoph Erhardt <[email protected]>
This notation is supported by both GCC and Clang, whereas
`#pragma unroll` is only supported by Clang.
Signed-off-by: Christoph Erhardt <[email protected]>
Clang warns that forward-declaring a `struct` as `class`
'is valid, but may result in linker errors under the Microsoft C++ ABI'.
Signed-off-by: Christoph Erhardt <[email protected]>
This also fixes the `note-property` test which was hanging on my
machine. Turns out `$CC` was stuck waiting to read from `stdin`,
and as such I decided to write something into it.
Signed-off-by: Robert Bartlensky <[email protected]>
We used to compute a file UUID using only the hashes in the code
signature section. So we computes the same UUID even if two files
are differnet only in some field of the code signature section.
This reverts commit f3e1f728d3.
I'm not 100% sure why, but now the code signature verification works
way faster than before. Maybe it has improved in macOS 12.4 which was
released last month?
This reverts commit f6b661a9051f5657ac701ea9c94dd54a85499365.
We want to make it possible to run two or more mold's `main` function
simultaneously in a single process, so we don't want to make `opt_demangle`
a global variable. That's why it was a thread-local variable.
The output now roughly matches the lld report format, with
each symbol followed by a limited list of places that reference it.
Lld can additionally read debuginfo to report the exact location,
but that would require writing an interpreter for .debug_line.
Signed-off-by: Luboš Luňák <[email protected]>
Setting it on demand is racy, and also not necessary, it's enough
to set it together with ctx.arg.demangle .
Signed-off-by: Luboš Luňák <[email protected]>
`bool foo : 1` is better `u8 foo : 1` because
struct {
bool foo : 1 = 0;
} bar;
bar.foo = 0xf000;
sets `bar.foo` to 1 while
struct {
u8 foo : 1 = 0;
} bar;
bar.foo = 0xf000;
does _not_ set `bar.foo` to 1 because it just truncates a given
integer to one bit and assign it to `bar.foo`.
It looks like SHA1 is slightly faster than SHA256 on a 2021 ARM Mac mini.
SHA1 is not recommended anymore, but for ad-hoc code signing, it should
be enough because anyone can just recompute an ad-hoc code signature for
any arbitrary binary.
We need to compute SHA256 hashes for a __code_signature section,
so recomputing a SHA256 hash of an entire file for an LC_UUID is
a waste of time. We can instead compute it as a tree hash.
We eliminate unneeded symbols at the end of the algorithm, but that
didn't save too much space. In fact, I didn't observe any difference
by eliminating that last step from the algorithm.
This is an unusual scenario, but it can happen on Arch Linux, where
apparently even crt1.o has no .debug_info . So if one for whatever
reason omits -g for all compilations and then uses --gdb-index,
mold aborts.
Signed-off-by: Luboš Luňák <[email protected]>
It was accidentally mapped to --color-diagnostics=always, but it
was a bug. For the sake of compatibility with other tools such as
clang or lld, it should be defined as an alias for `auto`.
Previously, we detected if a given linker plugin supports get_symbols_v3
or not and restart the process if only get_symbols_v2 is supported.
Now, mold restart itself wehn get_symbols_v2 is called for the first time,
eliminating the need for the feature detection.
https://github.com/rui314/mold/issues/454
Previously, if a relocation in an non-alloc section refers a section
fragment, it gets a tombstone value instead of a real value.
Fixes https://github.com/rui314/mold/issues/490
- Rename data types so that we have LittleEndian and BigEndian types.
- Do not assume that "base" integral types are aligned to 2 bytes
boundaries, because that doesn't make much difference in terms of
performance.
- Remove `pu8` type
Core part of this change is cleaning up Mold from UBSan alignment errors.
Following approach inspired by LLVM's ELFTypes is done here:
1. Introduce generic Packed class acting as proxy for unaligned aggregated value.
Every access to such value through proxy is secured by memcpy call.
2. Replace plain struct members with Packed members wherever it matters.
3. Use explicit castings through Packed type for misaligned loads.
For more background please check: https://github.com/rui314/mold/discussions/477
Signed-off-by: Dawid Jurczak <[email protected]>
`off_t` is either an alias for `off32_t` or for `off64_t` on a 32-bit
machine. `off32_t` is the default. But it looks like LLVM gold plugin
is always compiled with `off64_t`.
Because of this difference, the offset of the `handle` member in
`PluginInputFile` differed between mold and LLVMgold.so. mold thought
that the member was at offset 16 of the struct, while LLVMgold.so
thought that it's at offset 24.
That caused a mysterious crash when LLVMgold tries to access the
`handle` member.
Fixes https://github.com/rui314/mold/issues/483
If a given linker LTO plugin does not support the v3 API, we resolve
all symbol names to identify the set of object files that are actually
needed for linking and then restart the linker to do the same thing
again from scratch, excluding the unneeded files from the beginning.
We do this because the v2 API does not provide a way to "unload" an
object file once it is read.
To identify an unneeded object file on the second run, we serialize
its name in the form of `<archive-name>:<offset-in-archive>` or just
a filename. If an object file is in a thin archive, we simply used
its filename.
But if the same file is directly given to a linker as well as as a
thin archive member, the file would accidentally be excluded on the
second run.
This change fixes that issue. With this change, it looks like we can
build GCC 12 with LTO using mold.
Fixes https://github.com/rui314/mold/issues/454
Previously, Symbol::sym_idx overflows if there are more than 524,288
symbols in a single file. That's a very large number but is not impossible.
Fixes https://github.com/rui314/mold/issues/405
Previously, if a symbol in a non-IR object is weak or common and
is resolved to an IR symbol, mold internalized that symbol. That
resulted in having two separate definitions for the same symbol
and caused a mysterious error.
Fixed https://github.com/rui314/mold/issues/479
This is a LLD exclusive option that is not supported by LLVMgold. It
will be broken, so remove it for now.
Fixes: 7ebd0712 ("[ELF] Recognize --thinlto-{single-module,cache-dir,cache-policy}")
Signed-off-by: Tatsuyuki Ishi <[email protected]>
We cannot always write to argv safely becasue mold-wrapper's functions
run in other program's context, and we have no idea about the assumption
that the underlying program has on this vector.
So, we should not write to argv.
This commit is based on @ishitatsuyuki's patch.
Fixes https://github.com/rui314/mold/issues/478
And there is probably little need to do so, since it's DWARF4-only
and requires explicit -fdebug-types-section, but at least detect
and abort in this case.
My last commit d391fd9a59 changes how we
resolve versioned symbols, but that affected too many programs.
In particular it broke GCC build, so reverted in
f378fdc495.
This commit is an attempt to fix the same issue with a minimal change.
Fixes https://github.com/rui314/mold/issues/475
Apparently these also may get used with large enough binaries,
despite being somewhat tricky with regard to endianess.
Signed-off-by: Luboš Luňák <[email protected]>
The current code assumes the debuginfo address size is equal to the
native address size, which should be the case, but check that just
in case it isn't.
Otherwise the test may fail simply because .gdbinit setup does
something strange (I happen to have 'set auto-solib-add off', which
disables loading debug info by default).
An object file can contain both unversioned and versioned symbols for
the same symbol. For example, the following piece of code will be
compiled to an object file that will contain `foo` and `foo@VERSION`.
void foo() {}
asm(".symver foo, foo@VERSION");
If this object file is given to GNU BFD linker, it exports only
`foo@VERSION` and suppresses `foo`. I believe the rationale for doing
that is, if a symbol is versioned, all of its versions must be
versioned. In other words, `foo@VER1`, `foo@VER2` and `foo@@VER3` can
co-exist, but `foo@VER1` and `foo` can't. In the latter case, if you
want to provide `foo` as the default version, it should be exported
not as `foo` but as `foo@@SOME_VERSION` (with double at-signs).
Fixes https://github.com/rui314/mold/issues/426
Previously, our output for .gdb_index depended on the iteration order of
ConcurrentMap. Since the iteration order varies on every run of the linker
due to thread scheduling randomness, our .gdb_index were different on
every lihnker invocation.
In mold, we guarantee that our output is the same as long as the same
command line options and input files are given to the same version of mold.
So the situation clearly violated the rule.
This commit fixes that issue.
GCC creates a .debug_macro section if -g3 is given. That section
is in a comdat group, but the section is directly referred by another
section, which is a violation of the ELF spec.
If a section is deduplicated, we handle any references to that section
as if they had value 0. But that causes a mysterious gdb slowdown.
So we can't set 0 for a dead .debug_macro section.
In this commit, we simply stop deduplicating .debug_macro sections.
This will bloat up debug info, but that's better than producing an
effectively non-debuggable binary.
Fixes https://github.com/rui314/mold/issues/357
Fixes https://github.com/rui314/mold/issues/438
GDB crashes in that case in dw2_find_pc_sect_compunit_symtab()
for a reason I do not understand. This is presumably what I was
trying to avoid already in e0dd53b4ad
but didn't quite manage (so reverting that part).
Signed-off-by: Luboš Luňák <[email protected]>
This one form has an extra uleb field directly in .debug_abbrev,
so it needs to be skipped too. This is not a problem with Clang,
as that one seems to always put DW_TAG_compile_unit first
in .debug_abbrev, but GCC with DWARF5 doesn't and this code
didn't find it.
Another stylistic minor problem in this code was that abbrev_code
and has_children weren't skipped over, although that got silently
handled by the first iteration where the 1-byte has_children
flag was read as 1-byte uleb.
If start of the previous is used, gdb crashes for me, but end seems
to be fine. I'm not sure why, but I think end is better because
that is an address that is one beyond the end, so it shouldn't match
anything, or maybe end shouldn't be 0.
Also set some CU index, otherwise those random bogus values look
strange when dumping the content.
Signed-off-by: Luboš Luňák <[email protected]>
The value is an index (offset by DW_AT_rnglists_base) into the first
part of .debug_rnglists, which is a list of offsets into the second
part of .debug_rnglists, which lists ranges, each entry starting
with a value describing how to interpret the data.
Signed-off-by: Luboš Luňák <[email protected]>
The value is not the address, it's an index into .debug_addr
that's additionally offset by DW_AT_addr_base.
Signed-off-by: Luboš Luňák <[email protected]>
Handling properly e.g. DW_FORM_loclistx is non-trivial and
actually not needed at all for .gdb_index, so it's enough to know
how to skip it. For the reading function it's enough to handle
only those forms that are needed by DW_AT_low_pc, DW_AT_high_pc
and DW_AT_ranges (and AFAICT the function now includes all of those,
although for some of them the implementation is incorrect).
Signed-off-by: Luboš Luňák <[email protected]>
For DWARF5 split debug .o's get a slightly different .debug_info
entry that's larger, but for the purpose here it's otherwise
the same.
Signed-off-by: Luboš Luňák <[email protected]>
DWARF4 2.17.3 says that an entry where start address is the max
possible offset is a base selection entry and the end address
is actually a value to add to all addresses. The gdb_index spec
doesn't say if this entry is allowed in the address list, but
gold doesn't include it, so apply and drop it too.
Signed-off-by: Luboš Luňák <[email protected]>
It uses different sizes for some fields, and the dwarf mold code
is not ready to read it (it'd need converting those relevant calls
from reading u32 to optionally reading u64 instead).
Signed-off-by: Luboš Luňák <[email protected]>
.gdb_index contains two maps: a map from identifiers (type names,
function names or variable names) to compunits, and a map from
function address ranges to compunits. The latter is harder to create
because we needed to parse DWARF debug records to read function
address ranges. We generally don't want to do that.
This commit stops emitting address ranges. Now, .gdb_index sections
created by our linker contains the zero-length map as address ranges.
Though I'm not 100% sure if this is actually OK, it looks like gdb
works fine with that. It's at least worth a try.
https://github.com/rui314/mold/issues/439https://github.com/rui314/mold/issues/396
This test fails on some Linux systems, and it is essentially testing
not the mold's capabilities but the running platform's capabilities.
I don't think there's a portable, guaranteed way to create an
executable shared object on Linux, so even if it happens to work,
I don't think we can guarantee that.
mold is usually built for all supported tagets, namely, x86-64, i386,
ARM32, ARM64 and RISCV64. This is a good thing because it makes cross
compilation easy. That is, as long as you have a copy of the mold linker,
it is guaranteed to work as a cross linker.
However, during a quick debug session in which you build mold many
times, you may want to build mold only for your native target. That
greatly reduces build time because it reduces the amount of code
after template instantiation.
Therefore, in this commit, I introduced new macros,
MOLD_DEBUG_X86_64_ONLY and MOLD_DEBUG_ARM64_ONLY, to build mold for
x86-64 and ARM64 only, respectively.
These flags should never be used for production. They are solely for
debugging purpose.
Previously, --gdb-index tries to read bogus compressed data from
input sections if input debug sections are compressed.
Fixes https://github.com/rui314/mold/issues/431
I didn't want to write a Python one-liner in the Makefile, but it
looks like it is in practice one of the most portable way to compute a
relative path.
https://github.com/rui314/mold/pull/425
This affects Fedora >= 35, where debuginfod is enabled by default. On
such systems, gdb shows the following interactive prompt and then waits
forever:
```
This GDB supports auto-downloading debuginfo from the following URLs:
https://debuginfod.fedoraproject.org/
Enable debuginfod for this session? (y or [n])
```
Unsetting the `DEBUGINFOD_URLS` environment variable disables the prompt
as documented here: https://fedoraproject.org/wiki/Debuginfod#Disabling
Signed-off-by: Christoph Erhardt <[email protected]>
Previously, if a section has a very large alignment requirement,
that section and the following sections may get wrong file offsets.
Fixes https://github.com/rui314/mold/issues/405
This is a tough one because .gdb_index, .debug_gnu_pubnames,
.debug_gnu_pubtypes and DWARF are underdocumented, and DWARF is
complicated even if you have a right documentation. But, I believe I
managed to create a correct .gdb_index section.
Just like ld.lld, mold's --gdb-index needs all input object files to
have been compiled with -ggnu-pubnames. We read symbol names and type
names from the sections generated by -ggnu-pubnames.
Unlike ld.gold and ld.lld, we do not use an external library to read
DWARF debug info records.
As always, this feature is implemented with speed in mind. For Clang
15 which is built with -ggnu-pubnames, mold takes ~150 ms to create a
~300 MiB .gdb_index section on a simulated 16-core machine.
Fixes https://github.com/rui314/mold/issues/396
This patch fix memory leak reported by Memcheck while running some tests.
The problem happen even with --no-quick-exit option.
Before change there are blocks definitely and indirectly lost seen in Memcheck summary:
==1202== LEAK SUMMARY:
==1202== definitely lost: 1,120 bytes in 14 blocks
==1202== indirectly lost: 633 bytes in 12 blocks
==1202== possibly lost: 56,408 bytes in 46 blocks
==1202== still reachable: 128 bytes in 1 blocks
==1202== suppressed: 0 bytes in 0 blocks
After change number of such blocks drops to zero:
==2137== LEAK SUMMARY:
==2137== definitely lost: 0 bytes in 0 blocks
==2137== indirectly lost: 0 bytes in 0 blocks
==2137== possibly lost: 56,408 bytes in 46 blocks
==2137== still reachable: 128 bytes in 1 blocks
==2137== suppressed: 0 bytes in 0 blocks
Signed-off-by: Dawid Jurczak <[email protected]>
It is very rare, but technically you can create a shared object that
can also be executed directly. You can do that by giving a dynamic
linker path to the linker.
https://github.com/rui314/mold/issues/422
With this change, you can link a simple bootloader using mold.
To do so, compile bootloader source files to object files with
the `-fno-PIC` flag and then invoke mold on the object files with
`-Ttext=<bootloader-start-address>` and `--oformat=binary`.
The .text segment is usually at the beginning of the output file if
the file is created that way. By passing the startup code as the first
file argument to the linker, you can place that startup code at the
beginning of the file.
Fixes https://github.com/rui314/mold/issues/418
Previously, we make all PLT entries canonical if we are creating
a position dependent executable, because I was thinking that promoting
usual PLT entries to canonical ones is harmless; symbol equality still
holds.
However, it looks like Qt depends on the usual linker's behavior not
to make PLT canonical if not necessary. I believe they are maintaining
some hidden symbol as aliases for exported symbols and compare their
addresses at runtime.
Of course this doesn't work if your program is not compiled with -fPIC,
but qt5/QtCore/qglobal.h has a macro to abort compilation if PIC is
disabled. (They check for __PIC__ and __PIE__ macros.) So, all object
files are guaranteed to be compiled with -fPIC if they are using QT
functions, and they assume that the linker doesn't create a canonical
PLT for Qt functions.
This commit makes mold to create canonical PLTs only when needed.
That is, if an address of a function is directly taken (i.e. not via
GOT), then mold makes its PLT canonical.
Fixes https://github.com/rui314/mold/issues/352
glibc's -static-pie implementation expect that _GLOBAL_OFFSET_TABLE_
is at the beginning of .got.plt, as it uses the address of _DYNAMIC
which is stored at _GLOBAL_OFFSET_TABLE_[0].
In this patch, we always create .got.plt for x86-64 and i386.
With this change, you can now cross compile test cases and run
them on qemu-user. Here is an example to run our test suits in
an emulated ARM32 environment.
$ CC=arm-linux-gnueabihf-gcc \
CXX=arm-linux-gnueabihf-g++ \
GCC=arm-linux-gnueabihf-gcc \
GXX=arm-linux-gnueabihf-g++ \
OBJDUMP=arm-linux-gnueabihf-objdump \
MACHINE=arm \
QEMU='qemu-arm -L /usr/arm-linux-gnueabihf' \
make -j16 test
While running tests on UBSan instrumented mold binary 2 separated problems are reported:
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior elf/main.cc:592:15 in
elf/output-chunks.cc:1866:24: runtime error: member call on null pointer of type 'mold::elf::VerdefSection<mold::elf::X86_64> *'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior elf/output-chunks.cc:1866:24 in
elf/input-files.cc:1000:8: runtime error: load of value 190, which is not a valid value for type 'bool'
This change fixes both of them.
Signed-off-by: Dawid Jurczak <[email protected]>
ARM32 object files usually contain a .ARM.attributes section.
We need to parse and merge .ARM.attributes sections.
But for now, we just remove them from inputs.
Currently, we do not support relaxations of TLS GD/LD relocations
for ARM64. This is in practice not a problem because TLSDESC is used
on ARM64 by default.
However, there's one situation in which not supporting TLS GD/LD
relaxation becomes an issue; static linking. If an executable is
statically-linked, relaxation is mandatory because we can't generate
dynamic relocations for GD/LD relocations.
In this patch, we simply report an error if an object file compiled
with TLS GD/LD is used for creating a statically-linked executable.
This commit fixes all tests on ARM64.
Implement support for the R_AARCH64_LD_PREL_LO19 relocation type. Since
this actually behaves the same way as R_AARCH64_CONDBR19, reuse the
relevant code.
Signed-off-by: Alois Wohlschlager <[email protected]>
For a static position-independent executable, a libc's intitialization
routine reads the dynamic relocation table and apply them. It looks like
on ARM64, they simply apply relocations from the begining of the table
to end. Therefore, if an IFUNC relocation appears before RELATIVE relocs,
the IFUNC resolver would see an unrelocated value. So, we need to place
RELATIVE relocs before IFUNCs.
Fixes https://github.com/rui314/mold/issues/382
Some `ldd` impls don't support the --version option. We do not
want to show the error message but instead just skip the test
entirely.
https://github.com/rui314/mold/pull/385
After a certain point, it is not expected that there's a remaining
undefined symbol. -noinhibit-exec did not respect that invariant,
which caused a crash bug on ARM64.
This change forces all symbols to be resolved if --noinhibit-exec
is given.
Fixes https://github.com/rui314/mold/issues/383
We unset `LANG`, but it looks like `LC_ALL` takes precedence over `LANG`,
so we should set `LC_ALL` to `C`.
Reported at https://github.com/rui314/mold/pull/385
mold 1.1.1 generates `-static-pie` code that works with glibc 2.35 but
segfaults with glibc 2.34 or older.
Signed-off-by: Christoph Erhardt <[email protected]>
Previously, mold did not work with the -static-pie compiler flag.
In order to support static PIE, we need the following:
1. Create a .dynamic section even if it is not a dynamic executable, and
2. do not define __rel_iplt_start/end symbols.
The second part is required to workaround a glibc issue.
Even with these changes, mold-generated executable doesn't work with
old glibc versions. But I think it's OK because -static-pie is relatively
new option and you need a newer toolchain anyway.
It looks like the glibc loader does not use this field in the dynamic
section. GNU ld, gold and LLVM lld don't create this. So I think we
can just follow suit.
In C++, the size of an empty class is 1 rather than 0 because every
object is guaranteed to have a unique address. But if we do not need
the unique address guarantee, we can add `[[no_unique_address]]` to
a class member to save 1 byte. This is a new C++20 feature.
Previously, we set the address of `_GLOBAL_OFFSET_TABLE_` to `.got.plt`
on i386 and x86-64 and to `.got` on other targets. But it looks like
this special treament of x86 isn't necessary. The x86-64 psABI said
that the symbol can even be in the middle of `.got` (*1). If `.got.plt`
is missing, GNU linker set it to `.got`.
This commit unconditionally set the symbol value to `.got`.
(*1) x86-64 psABI 1.0 p.77: "The symbol _GLOBAL_OFFSET_TABLE_ may
reside in the middle of the .got section, allowing both negative and
non-negative offsets into the array of addresses."
Despite its comment, gcc sometimes failed to optimize the loop into
single `bswap` instruction. So it looks like we should explicitly use
`__builtin_bswap` functions.
Usually, init_array is readable and writable, but it looks like rustc
with `-C lto=fat` create a read-only .init_array. mold used to create
two output .init_array sections for read/write and read-only
init_array input sections. That caused one of them are not executed
on startup.
Now, mold create read/write .init_array output section even if an
input .init_array section is read-only.
Fixes https://github.com/rui314/mold/issues/363
We used to emit the following sequence for each PLT entry.
0xf3, 0x0f, 0x1e, 0xfa, // endbr64
0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOTPLT
0xe8, 0, 0, 0, 0, // call PLT[0]
In the above instruction sequence, `jmp` was expected to jump to the
following `call` instruction if the PLT entry is executed for the
first time. However, it wouldn't work because we needed another
`endbr64` before `call`.
This problem should be fixed in this commit. Now, the PLT header is
32 bytes long and each entry is 16 bytes.
IBT-enabled PLT section is sparse as 2/3 of the section contents are
NOP instructions. In this patch, I implemented alternative instruction
sequences for IBTPLT, so that each IBTPLT entry occupies only 16 bytes
instead of 32 bytes.
In return, our new IBTPLT section needs a 64 bytes header instead of a
16 bytes one, but it's overall a good deal because we usually have many
PLT entries.
When we relax R_X86_64_TLSGD or R_X86_64_TLSGD, we rewrite two
instructions (the one referred by TLSGD/TLSLD and the following one
referred by the following relocation). The second instruction is
usually 5 bytes, but if it can be longer than that, and if that's the
case, we need to emit a nop to fill the gap at the end of the longer
instruction.
We didn't do that. As a result, the remaining garbage of the second
instruction is executed and caused an unpredictable result (illegal
instruction or segv).
This patch fixes the issue.
Fixes https://github.com/rui314/mold/issues/360
This option reverse input sections before assigning offsets to them.
This is useful to detect an unintended dependency between static
initializers in different translation units. C++ only guarantees that
static initializers are invoked from top to bottom in a single
translation unit, and it doesn't guaratee anything about the order of
initialization between translation units.
By (partially) reversing the contents of .init_array using
--reverse-sections, you can run your program with a completely
reversed initialization order.
The test expects an error when an object compiled with `-fno-PIC` is
linked with `-pie`, but that doesn't happen on aarch64.
Signed-off-by: Christoph Erhardt <[email protected]>
This commit removes build-static.sh because statically-linked mold
executable can't generally dlopen a shared library and therefore can't
load the linker LTO plugin.
Now, build-dynamic.sh is renamed dist.sh and recommended for general
use.
I think we don't need to create a tar file for binary distribution
for each Linux distro. Instead, we can create mold executable that
works on most Linux machines.
The new script, build-dynamic.sh, creates a mold executable with
libmimalloc, libtbb, libstdc++ and libcrypto begin linked statically.
I don't have a concern as to the availability of other libraries
(libc, libm, libz and librt) because they essentially exists on any
system.
This commit ensure that all symbol resolution results are cleared
after LTO, so that the following second symbol resolution will not
be affected by the previous results.
It looks like setting __TBB_DYNAMIC_LOAD_ENABLED to 0 is not enough
to make TBB not to call dlopen(). We need to unset __TBB_WEAK_SYMBOLS_PRESENT
as well.
Fixes https://github.com/rui314/mold/issues/348
When building with SYSTEM_MIMALLOC=1, linking with (assuming
shared) '-lmimalloc' is not enough to override C++ new/delete
with mimalloc versions, and 'mimalloc-new-delete.h' should be
included from one (and the only) translation unit as well.
Signed-off-by: Dmitry Antipov <[email protected]>
ELF object files returned by do_lto() may contain unforeseen undefined
symbols, so we can't call that function after the symbol resolution pass
because it can cause undefined symbol errors.
In the previous commit (c325cc039a),
I argued that PC-relative relocations are not representable if they
refer absolute symbols, and I made a change so that such relocations
are handled as errors.
Even though what I did is technically correct, that results in a failure
of an important use case of the weak undefined symbol. Here is why.
If you have an weak undefined symbol `foo`, you would use it as follows:
if (foo)
foo();
If `foo` is defined (i.e. has an address other than 0), `foo` is called.
If `foo` is undefined (i.e. has the address 0), the subsequent CALL
instruction will have an offset from the CALL instruction to address 0.
That displacement is computed at link-time. If the output is position-
independent, the call instruction may not have a correct displacement
from address 0 to the instruction at runtime due to base relocation.
However, that's not a problem in practice, because the function call
is guarded by `if (foo)`, and that will always evaluated to false
if `foo` is undefined. Therefore, the faulty `CALL` instruction will
never be executed.
So, that means we need to relocate PC-relative relocations against
absolute symbols even if doing so results in an incorrect result.
This patch implement that.
PC-relative relocations against absolute symbols are not representable
in position-independent code. In order to support such relocations,
someone has to compute `S + A - P` or subtract `B` as a base relocation,
but such dynamic relocations don't exist.
This is contrary to non-PC-relative relocations against non-absolute
symbols. In this case, we can simply use the base relocation (e.g.
R_X86_64_RELATIVE).
https://github.com/rui314/mold/issues/348
It looks like the option is supported only by gold, and it doesn't
make much sense to me to have this option along with more generic
--warn-textrel. So I want to remove this before the next release.
This patch removes the --shuffle-sections option that takes an
argument as I'm still thinking about a better name for the option.
You can still use `--shuffle-sections` that doesn't take an argument.
If a relocation's r_sym value is 0 (i.e. it refers the undefined symbol
at the beginning of the symbol table), it has to handled as if S were 0.
We used to handle as if S were -1.
In addition to that, even if a relocation needs a dynamic base relocation,
it doesn't mean its expression is always S+A. For example, calling an
absolute address needs a dynamic relocation but its expression is S+A-P.
Fixes https://github.com/rui314/mold/issues/348
This reverts commit ddcb7b4197. `is_dso`
is used by hot functions such as `Symbol::get_addr()`, so we want to
eliminate the cost of virtual function dispatch.
read_lto_object is called on each archive member, so if an archive file
contains lots of members, it can exhaust the pool of file descriptors.
This patch fixes the issue by opening an archive only once.
Since compiled IR objects may contain mergeable string sections, we
don't know the estimated number of items in output mergeable sections.
Previously, we created the concurrent hash tables for output mergeable
sections before compiling IR objects, so there was a chance to see
the "concurrent hash table full" error.
This commit moves the code to add section pieces to output mergeable
sections after `do_lto`.
If the --shuffle-sections is given, mold now randomize the output by
shuffling input sections randomly. This feature is compatible with lld's
--shuffle-sections=SEED option introduced in
https://reviews.llvm.org/D74791.
This feature is useful when you want to equalize the conditions of
benchmarks. That is, some particular memory layout can produce a very
good benchmark number due to hardware-level cache hit rate or something
like that. Therefore, even if you get a good benchmark number after
changing code, there's a chance that that's caused by the layout change
and not by the new code itself. With --shuffle-sections, you can isolate
that.
The other use case I can think of is to enhance security. If you build
your program as a position-independent executable, the kernel
automatically enables ASLR (Address Space Layout Randomization), but ASLR
only shift the entire program image in memory by some random offset;
Relative offsets between sections remain the same. If you compile programs
from source, by using --shuffle-sections, you can make the offsets
unpredictable to attackers.
The LTO plugin API support is still in progress, but with this change,
mold can link itself with `-flto` with both GCC and Clang.
Since mold now supports LTO natively, I removed the fallback mechanism
to ld.bfd or ld.lld that I implemented in
a5029d19a8.
Fixes https://github.com/rui314/mold/issues/181
I believe if you make the destructor a protected function, you can't
destruct it through a pointer to the base type. All destruction has
to be called through a pointer to a derived type.
There's no difference at the moment, but I think it is more conventional
to make a virtual destructor public.
Add 'mold::macho::InputFile()::~InputFile()' as suggested by
clang++-13's '-Wdelete-non-abstract-non-virtual-dtor':
/usr/include/c++/11/bits/unique_ptr.h:85:2: warning: delete
called on non-final 'mold::macho::ObjectFile<mold::macho::ARM64>'
that has virtual functions but non-virtual destructor
[-Wdelete-non-abstract-non-virtual-dtor]
Signed-off-by: Dmitry Antipov [email protected]
RISC-V object files contain a large number of local symbols. This is
because all branches are explicitly represented by relocations and
symbols even their branch targets are of the same input section.
RISC-V psABI requires such relocations and symbols to allow sections
to be shrinked by linker relaxation.
GNU ld by default discard local symbols if RISC-V. We do the same
in this patch.
Prefer pure virtual 'mold::macho::InputFile::is_dylib()' (actually
implemented in 'mold::macho::ObjectFile' and 'mold::macho::DylibFile')
over the field of the same name, adjust related code. This is Mach-O
counterpart of 249c331117.
Signed-off-by: Dmitry Antipov [email protected]
`-icf=all` couldn't handle very small programs that has no sections
to process in the main loop. This commit fixes that crash bug.
Fixes https://github.com/rui314/mold/issues/332
Prefer pure virtual 'mold::elf::InputFile::is_dso()' (actually
implemented in 'mold::elf::ObjectFile' and 'mold::elf::SharedFile')
over the field of the same name, adjust related code.
Signed-off-by: Dmitry Antipov [email protected]
Currently, the sections we create for copy relocations are named .dynbss
and .dynbss.rel.ro. Section names shouldn't be significant in ELF
executables, so we should be able to name them as we want.
However, in practice, valgrind treat a section with the name .dynbss
in a special way and crashes if an executable contains both .bss and
.dynbss due to the following assertion failure:
$ valgrind ./prog
==1960252== Memcheck, a memory error detector
==1960252== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1960252== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==1960252== Command: ./prog
==1960252==
valgrind: m_debuginfo/readelf.c:2271 (vgModuleLocal_read_elf_debug_info): Assertion 'di->bss_svma + di->bss_size == svma' failed.
Segmentation fault (core dumped)
This commit is a workaround for the valgrind issue. We simply rename
dynbss and .dynbss.rel.ro to .copyrel and .copyrel.rel.ro, respectively.
Fixes https://github.com/rui314/mold/issues/159
Ensure that all xxhash functions are inlined. Since it eliminates
external dependencies, we no longer have to link against libxxhash.a
or libxxhash.so at all.
`SYSTEM_XXHASH` Makefile variable has been removed because it is
no longer relevant.
This is a mold-only experimental feature. If the flag is given,
mold prints out dependencies between input files as tab-separated
tuples of (`source-file`, `dest-file`, `symbol`). Each line of the
output means `source-file` depends on `dest-file` to use `symbol`.
With the dependency information, you can analyze for example why
some archive file member is included in a linker's output.
You can also for example know what symbols have to be removed
to eliminate the dependency to some shared library file.
I'm not sure if I'll include this flag in the next release or
document this feature, but it looks promising so far. If you like
or dislike this feature, please leave a comment on GitHub.
This is an example of the output when linking mold with mold:
https://gist.github.com/rui314/e1d70bbdebfabb881be7167314b58f48
We use only `XXH3_64bits` from libxxhash, and it looks like the function
is an inline function, so there's actually no runtime dependency against
libxxhash.so.
GCC creates symbols in comdat groups as STB_GNU_UNIQUE instead of STB_WEAK
if it was configured to do so at build time or the -fgnu-unique option was
given. If mold is given two object files with and without STB_GNU_UNIQUE,
it could end up selecting a sybmol that is in a de-duplicated comdat group.
This is arguably just an ABI incompatibility. Two comdat groups must
contain the same contents if their identifiers are the same. But we
can't handle it as an error because it is not uncommon to link object
files compiled using Clang (or GCC without -fgnu-unique) to static
libraries built with GCC that produces STB_GNU_UNIQUE symbols.
This patch gives the same priority to STB_GNU_UNIQUE as STB_WEAK so that
mold won't select symbols in discarded comdat groups.
Frankly, the situation around STB_GNU_UNIQUE is a mess. That GNU extension
shouldn't have been added to the GNU toolchain in the first place.
It looks like GCC shipped with Linux distros are nowadays do not produce
STB_GNU_UNIQUE symbols by default, but we still need to handle them.
Fixes https://github.com/rui314/mold/issues/324
Previously, if a protected/hidden undef symbol is resolved to a DSO
symbol, mold didn't report a symbol undefined error.
Fixes https://github.com/rui314/mold/issues/329
Relocations are naturally sorted, so we don't have to sort them again.
This change makes Chrome link time ~1% faster when --pack-dyn-relocs=relr
is specified.
With this change, `ninja check-bolt` in LLVM passes. I'm not sure if
that really means mold is usable with Bolt, but I guess it is.
Fixes https://github.com/rui314/mold/issues/177
This commit adds the `--emit-relocs` option to mold. If the flag is
given, mold copies relocation sections from input files to an output
file. This option is used by some binary post-processing tools such
as Facebook's Bolt.
It looks like the relocations emitted by `--emit-relocs` are correct,
but I didn't do extensive testing. If you find any problem, please
let me know.
Fixes https://github.com/rui314/mold/issues/177
Prefer 'tbb::parallel_sort()' over 'std::sort()' in
'DynsymSection<E>::finalize()'. Although being highly
dependent from '--thread-count', this is expected to
achieve up to ~8x speedup for huge (>20M entries)
symbol tables, as shown with '--perf', e.g.
from:
1.651 0.000 1.662 DynsymSection::finalize
to:
0.488 0.000 0.198 DynsymSection::finalize
Signed-off-by: Dmitry Antipov <[email protected]>
Previously, we always uncompress compressed debug sections to
in-memory buffer before copying them to the final output buffer.
This patch eliminates that redundant copy whenever possible.
`--repro` is a hidden command flag for debugging.
Previously, if the flag was given, mold would create a `.repro`
section in an output file with all input files as its contents.
The flaw of the design is that when mold fails to create an output
file, no .repro section would be created.
So I changed the behavior in this commit. Now, the tar file is
created as an independent file.
`ubuntu:20.04` is a rolling docker tag, so the image pulled from it
is not guaranteed to be the same. We should speicfy the image ID
for reproducibility.
Fixes https://github.com/rui314/mold/issues/317
Add 'mold::elf::GlobPattern::Element' and 'mold::macho::SplitInfo'
trivial constructors to fix all '-Wmissing-field-initializers' as
reported both by g++ and clang++.
Signed-off-by: Dmitry Antipov <[email protected]>
OpenSSL deprecates the low-level crypto APIs in OpenSSL 3.0. I guess
there's a reason to do that for them, but for us, the low-level APIs
such as SHA256_CTX, SHA256_Update or SHA256_Final are exactly what we
want to use. After all, we just want to compute SHA256 checksums.
The high-level API that OpenSSL provides requires users to allocate a
context object using new_ctx(). That has some performance hit as it
requires heap allocation. And it's just complicated too.
So, I decided to stick with the deprecated functions at least for now
and just suppresss the warning message by defining
OPENSSL_SUPPRESS_DEPRECATED macro. If OpenSSL deletes these functions,
we need to do something, but it's too early to worry about it.
Fixes https://github.com/rui314/mold/issues/246
Before the change calls to $(shell git rev-parse) and $(shell pkg-config)
happened on every mold's .o file (as make's "A = $(B)" performs late
expansion).
After the change $(shell) calls are evaluated once with "A := $(B)"
assignment.
Noticed by chance when 'make' was complaining about missing pkg-config
tool on each build step.
Signed-off-by: Sergei Trofimovich <[email protected]>
As we add more targets to mold/ELF, it takes more time to compile
source files because compiler has to instantiate more templates.
I think we need to do something to fix it, but for now, I'll just
add a stub for RISC-V 64-bit ISA so that we can start working on
RV64.
This replaces the GCC builtins with their portable C++20 counterparts.
Note that the C++ functions are only defined for unsigned types, so we
need to explicitly specify the appropriate template type argument in
some instances.
Signed-off-by: Christoph Erhardt <[email protected]>
Otherwise fails with:
/usr/include/c++/v1/__threading_support:370:43: error: use of undeclared identifier 'PTHREAD_MUTEX_RECURSIVE'
200809L triggers __USE_XOPEN2K8 to be defined which enables pthread.h to
define the missing identifier.
Signed-off-by: Marc-Antoine Perennou <[email protected]>
musl libc doesn't provide getcontext/setcontext functions.
It also doesn't define RTLD_DEEPBIND flag.
I already sent a pull request to upstream:
https://github.com/oneapi-src/oneTBB/pull/748
PT_GNU_RELRO works on page granularity. We always align the begining
of a RELRO segment to a page boundary, but the end was not. Since the
runtime conservatively align _down_ it to a page boundary, the last
page weren't be marked as read-only.
This patch makes the size of a RELRO always a multiple of the page size.
While an iterator may point beyond the last element of a `std::span`, a
pointer may not.
Fixes#298.
Signed-off-by: Christoph Erhardt <[email protected]>
It is up to packager's choice to create mold as a position-independent
executable or not. If you want, pass `LDFLAGS=-fpie` and `CXXFLAGS=-fPIE`
to `make`.
Our Makefile didn't allow overriding CFLAGS, CXXFLAGS or LDFLAGS
because we add mandatory options to these variables. It is contrary
to conventions Makefile conventions explained here.
https://www.gnu.org/prep/standards/html_node/Command-Variables.html#Command-Variables
In this patch, I separated mandatory options to MOLD_CXXFLAGS and
MOLD_LDFLAGS so that users can freely override CFLAGS, CXXFLAGS and
LDFLAGS.
I also removed `DEBUG`, `ASAN` and `TSAN` variables from the Makefile
because we can now simply pass `CXXFLAGS="-g -O0"` or
`CXXFLAGS=-fsanitize=...` instead.
The SerenityOS LibC doesn't leak the definitions of select(2) or struct
timeval into other POSIX headers. Manually include these headers in
elf/subprocess.cc where they are used for better compatibility.
Signed-off-by: Andrew Kaster <[email protected]>
Before this change, all bitmap entries ended up containing the value
0x3 (as `pos[i] - base` is guaranteed to be a multiple of the word
size). This expression needs to produce the offset in words from the
base address, so we need to *divide* by the word size.
Signed-off-by: Daniel Bertalan <[email protected]>
If the corresponding DT_RELR, DT_RELRSZ and DT_RELRENT dynamic entries
are not present, dynamic linkers won't pick up the relocations encoded
in .relr.dyn.
Signed-off-by: Daniel Bertalan <[email protected]>
To process version scriots, we have to match glob patterns against
symbol strings. Sometimes, we have hundreds or thousands of glob
patterns and have to match them against millions of mangled long
C++ symbol names. This step can be very slow.
In this patch, I implemented the Aho-Corasick algorithm to match glob
patterns to symbol strings as quickly as possible. For the details
of the algorithm, see https://en.wikipedia.org/wiki/Glob_(programming).
This patch improves mold's performance for programs that uses large
version scripts. For example, linking libQt6Gui.so.6.3.0 reduced from
1.10s to 0.05s with this patch.
This patch also changes how symbol versions are applied if two or more
version patterns match to a single symbol string. Previously, the last
one in a script file took precedence. Now, the first one takes
precedence. I believe the new behavior is compatible with GNU ld.
Fixes https://github.com/rui314/mold/issues/156
Fixed https://github.com/rui314/mold/issues/287
If you try to link ICC-generated objects file with GCC-generated objects,
you'll get an error message that `__gxx_personality_v0` is duplicated.
This is because ICC puts a section with this symbol into a GNU linkonce
section, while GCC puts it into a COMDAT section.
ICC should stop putting that symbol into GNU linkonce because it's
superceded by COMDAT long ago.
That being said, we need to do something to make it possible to mix
ICC and GCC object files. In this patch, we simply discard the ICC-
generated section. Since `__gxx_personality_v0` is always provided by
libc (that function handles C++ exceptions), we can simply ignore ICC's
output.
Fixes https://github.com/rui314/mold/issues/271
libtbb.so contains undefined symbols on Gentoo with musl libc.
Because we are not using such symbols at runtime, and symbols are
resolved lazily, mold would work fine as long as we can build it.
By passing `-allow-shlib-undefined`, we can build mold.
Fixes https://github.com/rui314/mold/issues/281
ARM64 branch instructions have only a 25-bit displacement. Non-thumb
instructions are always aligned to 4 byte boundaries, but with that
implicit trailing two zeros considered, they can represent only a 27-bit
displacement. That means branch instructions can jump to a location only
if it is within a ±128 MiB range.
If a branch destination is farther than that, a linker has to emit machine
code sequence that constructs a full 32-bit address in a register to jump
to the final destination, and redirect the branch to that code sequence.
Such code sequence is called a "range extension thunk" or just "thunk".
Previously, mold didn't support range extension thunks, so it couldn't link
large programs. That would fail with an "relocation out of range" error.
Now, mold gained a feature to create thunks and can link large programs.
Thunk creation is an interesting algorithmic problem. We need to insert
a thunk for at least in every 128 MiB chunk, because otherwise branch
instructions wouldn't be able to jump to a thunk. Adding an entry to a thunk
could slightly enlarge the distance between a branch instruction location
and its destination if the thunk is in between them. That could make the
branch that was previously reachable unreachable.
Usually, this problem is solved by an iterative algorithm. With the
iterative algorithm, a linker check for reachability of all relocations,
create new thunks if necessary, and repeat it until no new thunks are
created.
I implemented a different algorithm than that in this patch. The algorithm
implemented in this patch is guaranteed to work in O(n) where n is the
number of relocations. This algorithm might be novel.
And the algorithm implemented in this patch is quite fast. It can create
thunks in 80 milliseconds on a 16-core Amazon Graviton 2 machine for
clang-14 that has an ~100MB .text section.
Previously, we didn't handle version scripts like this correctly:
ver {
global: *;
local: foo*;
}
We didn't handle `local:` part correctly except for `*`.
Fixes https://github.com/rui314/mold/issues/277
It should be perfectly legal to have an empty CIE along with an end-of-records
marker of FDE. /usr/lib/crtend.o from NetBSD/amd64 has the following .eh_frame
but mold emits an error for the zero-length FDE:
.section .eh_frame, "a", @progbits
.align 8
.quad 0
Signed-off-by: Masatake Daimon <[email protected]>
GCC 7.5.0 passes these flags to ld(1). Maybe mold should handle them properly,
but since common symbols are considered to be obsolete it's probably not worth
it. At least it's better to ignore them rather than to abort.
Signed-off-by: Masatake Daimon <[email protected]>
Some operating systems, like NetBSD, don't have a separate library for
dlopen(3). They have dl* functions in their libc.
Signed-off-by: Masatake Daimon <[email protected]>
We try to overwrite to an existing output file if exists because
writing to a file that is already in buffer cache is much faster than
creating a new fresh file and write to it.
Previously, mold failed with the "fchmod failed" error if an existing
file is writable (so open for read-write succeeds) but owned by
someone else (so fchown fails). Now, mold ignore such existing file
and create a fresh output file.
Fixes https://github.com/rui314/mold/issues/275
A function passed to tbb::parallel_scan must be associative, but I don't
think our function satisfied that constraint. So I rewrote code without
tbb::parallel_scan.
.relr.dyn is a new section that has been implemented in other linkers
recently. That section contains only the RELATIVE-type dynamic
relocations (i.e. base relocations). Compared to the regular
.rela.dyn, a .relr.dyn's size is typically less than 1/10 because the
section is compressed.
Since PIEs (position-independent executables) tend to contain lots of
RELATIVE-type relocations and PIEs are now the default on many Linux
distributions for security reasons, .relr.dyn is more effective than
it was. It can reduce binary size by a few percent or more.
Note that the runtime support is catching up, so binaries built with
`-pack-dyn-relocs=relr` may not work on your system unless you are
running a very recent version of Linux.
I believe this pseudo member is relatively new to support archive
files larger than 4 GiB. I'm not sure if mold can handle such large
archives, but first of all, mold crashes when an archive with this
pseudo member is given.
This commit fixes the crash bug.
I don't know how to create an archive with this pseudo member, so
this commit does not have a testcase.
Reported by sina-ht at https://github.com/rui314/mold/pull/269.
In mold, a relocation refers either a symbol or a section piece.
A section piece is a segment of a mergeable section such as
.rodata.str.1 or .debug_str.
Previously, we preprocessed all relocations referring mergeable
sections to find their corresponding section pieces. We did this
because we want to find a relocation target as quickly as possible
for `gc_sections` and `scan_rels`.
However, we didn't actually have to do that for non-alloc sections,
as non-alloc sections are not subject to neither `gc_sections` nor
`scan_rels`. So, we could skip relocation preprocessing for non-alloc
sections. This commit implement that optimization.
It looks like this is an effective optimization for programs that have
large debug info because debug sections tend to contain a lot of
relocations referring a .debug_str which is a mergeable section.
Here is a few notable examples.
Output size Before After
clang-14 2.2 GiB 1.455s 1.396s (4% faster)
mongodb 4.8 GiB 2.341s 1.925s (17% faster)
These nubmers were measured on a simulated 16-core 32-thread machine.
I believe they can be represented using dynamic relocations at runtime.
Since they are used rarely and there even seem to have no assembler
syntax to generate such relocations, I can't write tests for them.
gdb uses this field only if it is an executable. Having an extra
dynamic entry is usually harmless, but unfortunately, RPM's `rpmdeps`
tool uses the presence of this entry to distinguish executables from
shared object files. So, it is better not to create a DT_DEBUG entry
for shared object files.
Fixes https://github.com/rui314/mold/issues/254
That substring was introduced in de7ba9014f
to appease Gentoo's dev-libs/jansson-2.13.1-r1 package. But I think I
shouldn't done that from the beginning to avoid the sitaution of the
"User-Agent" string of the web browser, which everybody claims they
are Mozilla, AppleWebKit, Chrome and Safari simultaneously.
Previously, our parallel symbol resolution algorithm was not
deterministic in edge cases. As an example, consider the following two
source files:
foo.c:
inline void fn1() { ... }
bar.c:
inline void fn1() { ... }
void fn2() { ... }
Let's say you compile these files and put them into an archive file.
If mold decided to pull out `foo.o` first for `fn1` and then `bar.o`
for `fn2`, then both `foo.o` and `bar.o` are included into a result.
However, if mold pulled out `bar.o` first, then there's no chance for
`foo.o` to be pulled out, so only `foo.o` would be included into a
result.
The algorithm implemented in this commit should be deterministic.
We do not override symbols when we mark live objects.
Previously, the `bnd jmp` instruction in a IBTPLT entry jumps to the
middle of an instruction due to an incorrect GOTPLT value. That happened
to work because a value that was there after the jump can be interpreted
as an `add` instruction and the control falled through the next `pushq`.
Previously, mold ignored common symbols in an archive when resolving
symbols. As a result, even if an undefined symbol could be resolved
using a common symbol in an archive, mold would end up with an undefined
symbol error.
This commit changes the behavior. Now, an undefined symbol is resolved
to a common symbol in an archive if exists.
Fixes https://github.com/rui314/mold/issues/256
mold does not have to be built with clang/clang++, so don't use
these compiler frontends.
mold also doesn't have be built with g++ (GNU C++ compiler).
We use `c++` command instead.
Fixes https://github.com/rui314/mold/issues/261
The .ctors section contains a list of pointers that have to be run
before `main`. It usually contains pointers to global constructors.
The .dtors are for global destructors.
The .init_array and .fini_array serve the same purpose as .ctors and
.dtors. The former sections are newer than the latter sections, and
most programs have already migrated to .{init,fini}_array.
.ctors/.dtors are very similar to .{init,fini}_array, but the order
in which pointers are executed is different. .ctors/.dtors are executed
from the end to the beginning, while .{init,fini}_array are executed
from the beginning to the end.
Previously, we converted .ctors/.dtors sections into .{init,fini}_array
sections. In order to do that, we not only merge .ctors/.dtors to
.{init,fini}_array but also reverse their section contents, so that
the initialization order remains the same.
However, there was a bug in that logic. We forgot to reverse the
locations of dynamic relocations for the converted sections.
So, .ctors/.dtors sections converted to .{init,fini}_array were executed
in a wrong order.
We have two choices to "fix" the issue: (1) reverse not only section
contents but also dynamic relocations, or (2) stop converting .ctors/.dtors.
In this patch, I chose (2).
Since LLVM lld doesn't convert .ctors/.dtors, it shouldn't cause an
issue for most programs.
Previously, mold crashes due to an invalid regex pattern exception
when `[...]` is given as a version script pattern.
Fixes https://github.com/rui314/mold/issues/258
This reverts commit 4d78510cb0.
If the SHF_MERGE bit is set, sh_entsize must have the size of the unit
for that section. In the previous commit, we changed the behavior of
mold so that it sets SHF_MERGE bits in the output file. However, we
didn't set sh_entsize. So, the resulting section is technically invalid.
We merge sections with different sh_entsize into a single output
section, so there's no easy way to "keep" the original value.
In this commit, we simply revert the previous change so that mold won't
set SHF_MERGE in the output file.
https://github.com/rui314/mold/issues/155
Previously, mold put all global symbols into .gnu.hash. Although I
believe it was not an error, it bloated the size of .gnu.hash because
.gnu.hash needs only exported symbols.
https://github.com/rui314/mold/issues/255
Let Makefile know how to locate openssl header files in a directory other than
the default directories by using pkg-config. If you don't have pkg-config, then
$(shell) returns empty.
Signed-off-by: Hiroshi Takekawa <[email protected]>
This is very hacky but highly practical, so I couldn't resist to not
implement this. We should support LTO natively in the future. In the
meantime, this feature should work as a poor-man's replacement.
Fixes https://github.com/rui314/mold/issues/242
Let Makefile know how to link libcrypto in a directory other than the default
directories by using pkg-config. If you don't have pkg-config, then $(shell)
returns empty.
Signed-off-by: Hiroshi Takekawa <[email protected]>
Looks like some CUDA object files contains FDEs whose relocation has
r_sym with value 0. Such FDEs are dead and should be ignored.
Unfortunately, there's no easy way to produce an object file containing
such relocation, so this change lacks a testcase.
Fixes https://github.com/rui314/mold/issues/235
Follow the same behavior in the ELF version of read_input_files and
fatal in case no input files are given. This avoids a segfault in
successive functions when running `./ld64.mold` without any arguments.
Signed-off-by: Tobias Klauser <[email protected]>
Running mold on x86_64 macOS 11 currently leads to a segfault due to
inifinite recursion in do_main<X86_64>. Protect against this case by
only calling into do_main<X86_64> once if cputype doesn't match.
Signed-off-by: Tobias Klauser <[email protected]>
This makes it possible to build and test mold in a path that contains
whitespace characters - with the notable exception of the tests where
`LD_PRELOAD` is used. That's because `LD_PRELOAD` unconditionally treats
any whitespace as separator, regardless of quoting.
The following ShellCheck warnings are eliminated by this commit:
* SC2046: Quote this to prevent word splitting.
* SC2086: Double quote to prevent globbing and word splitting.
Signed-off-by: Christoph Erhardt <[email protected]>
For globbing, '?' matches a single character, so must be replaced
with '.'. As a result, don't skip the later regex matching for
version scripts, if the pattern contains either '*' or '?'.
Signed-off-by: Jan-Marek Glogowski <[email protected]>
Previously, if there are more than one TLS BSS section (e.g. .tbss and
.tcommon), mold layout them in such a way that they overlap in memory.
That caused a mysterious program crash to the programs compiled with DMD,
a D compiler.
Fixes https://github.com/rui314/mold/issues/126
We always write dynamic relocation addends for bug-compatibiltiy
with the Go toolchain. Therefore, this flag is no-op.
See 919e8cbc62 for the details of
the Go's bug.
Compiler should not emit these types of relocations unless it knows
they will never refer imported symbols. However, it looks like GCC 7
emits these relocations against global symbols with STB_GNU_UNIQUE
attribute, which can be resolved to a symbol in other ELF module at
runtime. It looks like the bug only exists in GCC 7 and fixed in
recent versions of GCC.
mold verifies the above conditions and reports an error if the
condition is violated. On the other hand, GNU ld and LLVM lld don't
verify and simply create a shared library that is not always
guaranteed to work.
Give this situation, I decided to simply remove the verification code
from mold. This is what other linkers do, and it make mold "compatible"
with GCC 7.
Fixes https://github.com/rui314/mold/issues/145
When we are creating a DSO, unresolved undefined symbols are promoted to
dynamic symbols by default so that they will get another chance to be
resolved at runtime.
You can suppress this behavior by passing `-z defs`. If that option is
given, remaining undefs are reported as errors instead of being silently
promoted.
It looks like `-warn-undefined-symbols` negates the effect of `-z defs`.
So, if both options are given, remaining undefs are promoted to dynamic
symbols. mold previously silently make such symbols absolute symbols with
value 0.
Fixed https://github.com/rui314/mold/issues/152
This allows the caller to pass extra build options if desired.
Moreover, it is possible to run `./build-static.sh test` in order to
execute the testsuite inside the container.
Signed-off-by: Christoph Erhardt <[email protected]>
These packages contain the i686 toolchain as well as the `file` and
`hexdump` utilities. They increase the size of the container image by
approximately 10 % (70 MiB).
Signed-off-by: Christoph Erhardt <[email protected]>
* Append the `Z` option for the mounted volume
* Add `--userns=keep-id` if Podman's `docker` wrapper is used
Signed-off-by: Christoph Erhardt <[email protected]>
This reverts commit 1baac27e8c.
In order to link gcc 7's output, relaxing this error check wasn't
enough as reported on https://github.com/rui314/mold/issues/145.
We need to remove more error checks or keep them as-is.
For now, I'll restore all the error checks, but before making another
release, I may remove all error checks to accept gcc 7's buggy
output files.
Once object files are linked into an executable or a shared object file,
sections are no longer splittable. So these bits don't make sense anymore.
Previously, we cleared the bits. But it looks like there are tools that
are picky about them. So we'll just leave them as-is.
Fixes https://github.com/rui314/mold/issues/155
This is an attempt to speed up version script application.
It looks like RE2 is faster than libstdc++'s std::regex.
This change reduces libQt6Gui.so.6.3.0's link time by about 30%.
https://github.com/rui314/mold/issues/156
In some environment, XXH3 isn't available as a binary package.
If you do not like to use the imported xxhash library but instead
link to system's libxxhash.so, invoke make with `SYSTEM_XXHASH=1`.
These test files are not only invoked by make by also directly by hand.
Unsetting `LANG` on each file so that they don't fail in a non-English
environment.
This change is mechanically created by the following command:
sed -i '1 a export LANG=' test/*/*.sh
If the tests are executed in a different locale like French, some logs (ex: ```out/test/elf/auxiliary/log```) can contain output like:
```La section dynamique à l'offset 0x2000 contient 10 entrées :```
which of course doesn't work as the grep is
```
fgrep -q 'Auxiliary library: [foo]' $t/log
```
Signed-off-by: Sylvestre Ledru <[email protected]>
Previously, if the following conditions are met:
- we are creating a shared object file,
- there's an undefined symbol in an input object file that are
to be promoted to a dynamic symbol, and
- a version script defining a default version is given,
then the symbol gets the default version. But that's a wrong behavior
because version scripts should not affect symbols that are not defined
in an output file.
This change fixes the issue by not setting version to such symbol.
Fixes https://github.com/rui314/mold/issues/151
* add missing -lrt flag to Makefile
vis #140
* update where -lrt is added to Makefile
* add -lrt in Makefile to appropriate line
Signed-off-by: Miguel Raz Guzmán Macedo <[email protected]>
Negligible saving and downstream, distributions usually recompress or
compress with their own specific options. Unconditionally compressing
man pages, while well intended, usually creates more hassle there.
Signed-off-by: Sam James <[email protected]>
- Respect user CXXFLAGS
- Rename CPPFLAGS (previously used in the sense of "flags for the C++ compiler") -> CXXFLAGS
- CPPFLAGS is generally used for "flags for the C(++) preprocessor.", so let's
use it for that
- Respect user LDFLAGS
(In one instance, we were respecting LDFLAGS, but doing it too late.
We need to pass LDFLAGS _before_ any objects in order for -Wl,--as-needed
to work correctly.)
Signed-off-by: Sam James <[email protected]>
Some packaging systems want to handle the stripping by themselves.
Setting e.g. STRIP=true will result in true being used instead of strip
and thus will skip the stripping part, leaving it to the package manager
Signed-off-by: Marc-Antoine Perennou <[email protected]>
Previously, an executable linked by mold could fall into an infinite
loop between .plt.got and .got entries. This commit fixes the issue
by creating .plt entries instead of .plt.got.
Fixes https://github.com/rui314/mold/issues/129
DMD, a compiler for the D language, generates a broken .rodata.str1.1
section with sh_entsize = 0. The section also contains out-of-bound
relocations. This patch handles such broken mergeable sections as
regular sections to workaround the issues.
Fixes https://github.com/rui314/mold/issues/126
Fedora dependencies were tested in a fresh Fedora 34 Docker container.
- Use all available CPU threads to speed up compilation.
- Add `sudo make install` step to make the mold binary available
system-wide.
- List Ubuntu instructions as compatible with Debian 11 (tested
in a fresh Docker container).
- Reorder the list of dependencies to be consistent between Ubuntu
and Fedora.
- Don't use a `$` prefix for commands to make copy-pasting easier.
- Fix warnings reported by markdownlint.
Signed-off-by: Hugo Locurcio <[email protected]>
I don't know if it is a bug in Clang 10, but the new code couldn't
compile on Linux because `YamlNode` was an incomplete type.
I changed the type from `unordered_map` to `map` to workaround the issue.
glibc 2.22 or prior have a bug that the dynamic linker (ld-linux.so.2)
crashes on `dlopen` if .rela.dyn and .rela.plt are not contiguous in
the `dlopen`-ed file and RTLD_NOW is specified. That bug was fixed in
https://github.com/gentoo/glibc/commit/fa19d5c48a6b36518ce68412e3bdde6bfa8aa4a6.
glibc 2.23 which includes the fix for the bug was released on 2016-02-18.
So, unless you are using glibc that is more than 5 years old, mold-
generated shared object files work fine with `dlopen`. But it is easy
to make the sections contiguous in file, so I'll commit this change as a
workaround for the bug.
Fixes https://github.com/rui314/mold/issues/120
Previously, mold created two or more ".rodata" sections if input files
contain regular .rodata sections as well as .rodata.str* or .rodata.cst*
sections. This is because .rodata.str* and .rodata.cst* contains mergeable
section contents (i.e. string constants and constant pools, respectively),
and they are handled in a special way.
In ELF, section names are not significant, so nothing is wrong with
creating multiple .rodata. However, valgrind unfortunately doesn't like
such executable.
With this change, mold keeps ".rodata.str" and ".rodata.cst" prefixes
to avoid creating multiple ".rodata" sections.
Fixes https://github.com/rui314/mold/issues/118
mold used to emit a spurious "recompile with -fPIC" error when creating
a position-dependent executable. This is because we alwyas create
dynamic relocations for importe symbols. If the relocated place is
read-only, we can't apply a dynamic relocation, and we printed out the
error message.
This patch fixes the issue by creating copy relocations and PLTs for
such symbols.
Fixes https://github.com/rui314/mold/issues/116
This is not a linker feature, but in order to learn how Mach-O
executables are constructed, I'll implement a dump feature.
I'll remove the feature once I understand the structure of Mach-O
binaries.
This command name is more comsistent with other linkers, i.e.,
ld.bfd, ld.gold and ld.bfd. mold will be a all-in-one linker that
is capable of cross-linking, and it should dispatch according to
argv[0] as follows:
- mold: a native linker
- ld or ld.mold: a Unix linker
- ld64.mold: a macOS linker
- mold-link: a Windows linker
475a250ad4 changed mold's behavior on
weak undefined symbols, so that if they are not resolved within the
current ELF module, they are resolved to address zero. Previously,
they would be promoted to dynamic symbols to give then another chance
to be resolved at runtime.
That change caused a regression in Firefox. Firefox uses weak undef
symbols as a mean to export symbols from libxul.so. Quote from
Firefox's mfbt/Types.h:
> On linux mozglue is linked in the program and we link libxul.so with
> -z,defs. Normally that causes the linker to reject undefined references in
> libxul.so, but as a loophole it allows undefined references to weak
> symbols. We add the weak attribute to the import version of the MFBT API
> macros to exploit this.
So, they use this as a "loophole".
This change partially revert 475a250ad4.
Now, remaining weak undefs are resolved to address zero only when we
are creating an executable.
Fixes https://github.com/rui314/mold/issues/114
We sometimes put local symbols into .dynsym, but if they are
global symbols hidden by a version script, they were exported
from .dynsym. This patch correctly makes them local symbols.
Previously, we try to promote unresolved weak undefined symbols to
dynamic symbols so that they will get another chance to be resolved at
runtime. This is not always doable. Consider the following two cases:
- There's a relocation that directly refers a weak undefined symbol
- There's a relocation that is in a read-only section
In the former case, we need to create a copy relocation, but we can't
do that against a weak undef becasue a weak undef doesn't have the notion
of the symbol size.
In the latter case, we need to create a dynamic relocation, but such
dynamic relocation would fail at load-time when the runtime linker tries
to mutate the contents of a read-only section.
So, we had a logic to detect the above cases and promote weak undefs
only when they can be promoted. But the logic is not as robust as I
hoped. So, in this patch, I removed the logic and stop promoting weak
undefs.
We shouldn't create TLSDESC dynamic relocations for statically-
linked executables because such executables don't contain the
tranpoline function needed for TLSDESC. Instead, we should
always relax these relocations.
We used to write only global symbols to .dynsym because, in most
use cases, .dynsym are used for resolving inter-module dependencies.
However, we need to put local symbols to .dynsym if they are thread-
local symbols.
Previously, we created dynamic relocations against read-only sections
if the sections contain relocations against weak undefined symbols.
Since such dynamic relocations cannot be applied at load-time, the
generated executables failed with SEGV.
Now, such relocations are resolved to address 0.
Reported at https://github.com/rui314/mold/pull/110
mold currently builds dependencies in its `Makefile` by explicitly
issuing `make -C ...` targeting the CMake build directory; this will
fail if a global `CMAKE_GENERATOR` environment variable is present that
specifies a different CMake build file generator.
Closes#91
Signed-off-by: Mahmoud Al-Qudsi <[email protected]>
This allows mold to build under clang++-14 which catches the write-only
`intptr_t drained` in `tbb/arena.cpp` as an unused parameter that
ultimately triggers `-Werror` to error out and abort the build.
It's 2021 and there are still projects that default to `-Werror` as the
default instead of using it only in the dev and CI environments... smh.
Closes#107.
Previously, only /usr/bin/ld, /usr/bin/ld.lld and /usr/bin/ld.gold
were intercepted. Now, mold ignores the directory part when comparing
a command name with `ld`, `ld.lld` or `ld.gold`.
This change is made because ld is often installed other than /usr/bin.
Fixes https://github.com/rui314/mold/issues/101
I was experimenting with cmake to see if it is useful for mold,
but it looks like using cmake doesn't make much sense for us.
So I'm undoing all changes that I did for cmake.
cmake is definitely better than autoconf, and it is also useful
if your program is cross-platform. However, neither of the benefits
don't apply to mold; mold doesn't need a complex feature detection,
and it currently supports only ELF-based Unix-like systems.
I think Makefile is a lingua-franca, while CMakeLists.txt isn't.
The good ol' Makefile works just fine for mold.
In the future, mold might become a cross-platform product, and if
that happens, we might want to re-introduce cmake.
Our assert() statements are pretty cheap. We want to enable them
even for release builds.
By default, cmake passes -DNDEBUG to disable assert() for release
builds. So, in this patch, we undefine it to re-enable assertions.
You can now build mold with the following commands:
$ mkdir -p out/debug
$ cd out/debug
$ cmake -GNinja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug ../..
$ ninja
To run tests, use the following commands:
$ cd out/debug
$ ctest -j$(nproc)
By default, std::atomic<T>::operator=() stores a given value with
the sequentially-consistent memory ordering, which is a very strong
memory order. We only need the atomicity of store in this case,
so we can use memory_order_relaxed instead.
This change improves performance when we have a lot of section
fragments.
This change shortens the time for garbage collection for clang-13
from 170ms to 100ms.
"oneTBB" used to be a git submodule, and it is now just a subdirectory.
Using the same directory name makes it difficult to switch between
branches. So I rename it "tbb".
Linking clang-13 with debug info takes ~3.6 seconds on a simulated
10-core/20-threads machine. mold spends most of its time (~2.3 seconds)
merging string literals in .debug_str. Input .debug_str sections contain
70 million string literals in total, which is reduced to 2 million after
de-duplication. The input object files contain a lot of duplicates.
clang-13 with debug info is enormous -- it is ~3.1 GiB after linking.
It looks like TBB's concurrent hashmap doesn't scale well with the
input.
In this patch, I implemented our own concurrent hashmap. The hashmap
is extremely lightweight and support only the key-value insertion
operation. It doesn't even support rehashing. It aborts once the hash
table becomes full.
In order to know the correct size for the hashmap before inserting
strings into it, I also implemented HyperLogLog algorithm in this patch.
HyperLogLog is an algorithm that gives a fairly accurate estimate on
the number of unique elements.
With this patch, mold can link clang-13 in ~2.5 seconds, which is ~30%
faster than before.
https://github.com/rui314/mold/issues/73
Previously, a GOT relocation (e.g. R_X86_64_REX_GOTPCRELX) and a
R_X86_64_64 relocation referring the same imported symbols were
resolved to different addresses. Here is why:
- When we saw a R_X86_64_64 relocation against an imported symbol,
we created a PLT and resolve the relocation there.
- GOT relocation is resolved to a GOT entry, which has a true
address of an imported function at runtime, which is different
from PLT entries that redirect calls to the real function.
With this patch, we no longer create a PLT entry for R_X86_64_64.
Instead, we emit a dynamic relocation so that it is always resolved
to a real function address.
Fixes GNU MP's `make check` failure, which was reported at
https://github.com/rui314/mold/issues/81
The grammar of the command is this
VERSION { <version-script> }
where <version-script> is a version script you can specify with
the --version-script option.
The default size and offsets of the .dynamic section are not necessarily
same with different builds of clang. For example, some builds can make
clang pass --hash-style=gnu to the linker and some --hash-style=both.
This change updates the test to compute the difference in size of the
.dynamic section before and after using the flag -spare-dynamic-tags,
making it independent of the compiler build.
Signed-off-by: Nehal J Wani <[email protected]>
mold: /__w/mold/mold/test/tmp/pie/a.o:(.text): R_X86_64_32 relocation
against symbol `.rodata' can not be used; recompile with -fPIE
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Signed-off-by: Nehal J Wani <[email protected]>
oneTBB API is changing rapidly, so even if a oneTBB is installed
into a system already, it is likely that that is not a compatible
version with mold. This makes program building unnecessarily hard.
This change intends to solve the problem once and for all by
including oneTBB as a subdirectory and static-link against it at
build-time.
oneTBB is released under the Apache License 2.0, which is compatible
with AGPL. Therefore, we can still distribute the binary of mold
under AGPL.
If you do not want to static-link oneTBB, pass `SYSTEM_TBB=1`
to `make`.
This change also ports mold from oneTBB v2020.3 to v2021.3.0.
Fixes https://github.com/rui314/mold/issues/66
I recommend users use the latest release instead of git HEAD
because HEAD may be broken in a subtle way. Before a release,
I build all Gentoo packages using mold, but I don't do that for
every commit because it takes ~2 days.
Delete this message and describe the bug here. Note that we only fix bugs in the most recent release of mold, so please make sure that you are using the most recent version.
This page explains the following warning message and how to fix it.
mold emits this message when it sees an object file that may not be
compatible with mold.
```
mold: warning: foo.o: this file may cause a segmentation fault because it requires an executable stack. See https://github.com/rui314/mold/tree/main/docs/execstack.md for more info.
```
# Background
On modern computers, the stack area (to which local variables are
stored) cannot contain executable code. If the control reaches the
stack area, the CPU refuses to execute any code there and the program
is usually terminated due to segmentation fault.
This is a security measure. The stack area used to be executable (old
CPUs generally execute any code as long as it is in a readable memory
region), but that provided an easy attack vector to a malicious user.
They wrote executable code to the stack area using some buffer
overflow bug and jumped there to run arbitrary code in a remote server
process.
To prevent this type of attack, the stack area is no longer executable
since the early 2000s. On Linux, the stack's executable-ness is
controlled by a bit in an executable, and the loader respects that
bit. The bit is set by the linker.
GCC had (and still has) a feature that depends on the executable
stack, so they invented a way to tell the linker to mark the stack
executable. Specifically, if an object file contains a
`.note.GNU-stack` section with the `SHF_EXECSTACK` bit, GNU linker
silently makes the stack of an output file executable.
But the GNU linker's behavior is dangerous. If you accidentally link
an object file that has that marker section, the entire stack area
silently becomes executable, disabling the security mechanism.
Therefore, mold simply ignores that marker section. If you are using
mold, you need to explicitly pass `-z execstack` to the linker to make
<!-- iframe showing the search results (closed by default) -->
<divid="MSearchResultsWindow">
<iframesrc="javascript:void(0)"frameborder="0"
name="MSearchResults"id="MSearchResults">
</iframe>
</div>
<divclass="header">
<divclass="headertitle">
<divclass="title">Data Structures</div></div>
</div><!--header-->
<divclass="contents">
<divclass="textblock">Here are the data structures with brief descriptions:</div><divclass="directory">
<tableclass="directory">
<trid="row_0_"class="even"><tdclass="entry"><spanstyle="width:16px;display:inline-block;"> </span><spanclass="icona"><spanclass="icon">C</span></span><aclass="el"href="group__analysis.html#structmi__heap__area__t"target="_self">mi_heap_area_t</a></td><tdclass="desc">An area of heap space contains blocks of a single size </td></tr>
<trid="row_1_"><tdclass="entry"><spanstyle="width:16px;display:inline-block;"> </span><spanclass="icona"><spanclass="icon">C</span></span><aclass="el"href="group__cpp.html#structmi__stl__allocator"target="_self">mi_stl_allocator</a></td><tdclass="desc"><em>std::allocator</em> implementation for mimalloc for use in STL containers </td></tr>
</table>
</div><!-- directory -->
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<divid="nav-path"class="navpath"><!-- id is needed for treeview function! -->
<!-- iframe showing the search results (closed by default) -->
<divid="MSearchResultsWindow">
<iframesrc="javascript:void(0)"frameborder="0"
name="MSearchResults"id="MSearchResults">
</iframe>
</div>
<divclass="PageDoc"><divclass="header">
<divclass="headertitle">
<divclass="title">Performance </div></div>
</div><!--header-->
<divclass="contents">
<divclass="textblock"><p>We tested <em>mimalloc</em> against many other top allocators over a wide range of benchmarks, ranging from various real world programs to synthetic benchmarks that see how the allocator behaves under more extreme circumstances.</p>
<p>In our benchmarks, <em>mimalloc</em> always outperforms all other leading allocators (<em>jemalloc</em>, <em>tcmalloc</em>, <em>Hoard</em>, etc) (Apr 2019), and usually uses less memory (up to 25% more in the worst case). A nice property is that it does <em>consistently</em> well over the wide range of benchmarks.</p>
<p>See the <ahref="https://github.com/microsoft/mimalloc#Performance">Performance</a> section in the <em>mimalloc</em> repository for benchmark results, or the the technical report for detailed benchmark results. </p>
</div></div><!-- PageDoc -->
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<divid="nav-path"class="navpath"><!-- id is needed for treeview function! -->
<!-- iframe showing the search results (closed by default) -->
<divid="MSearchResultsWindow">
<iframesrc="javascript:void(0)"frameborder="0"
name="MSearchResults"id="MSearchResults">
</iframe>
</div>
<divclass="PageDoc"><divclass="header">
<divclass="headertitle">
<divclass="title">Building </div></div>
</div><!--header-->
<divclass="contents">
<divclass="textblock"><p>Checkout the sources from Github: </p><divclass="fragment"><divclass="line">git clone https:<spanclass="comment">//github.com/microsoft/mimalloc</span></div></div><!-- fragment --><h2>Windows</h2>
<p>Open <code>ide/vs2019/mimalloc.sln</code> in Visual Studio 2019 and build (or <code>ide/vs2017/mimalloc.sln</code>). The <code>mimalloc</code> project builds a static library (in <code>out/msvc-x64</code>), while the <code>mimalloc-override</code> project builds a DLL for overriding malloc in the entire program.</p>
<h2>macOS, Linux, BSD, etc.</h2>
<p>We use <ahref="https://cmake.org"><code>cmake</code></a><sup>1</sup> as the build system:</p>
<divclass="fragment"><divclass="line">> mkdir -p out/release</div><divclass="line">> cd out/release</div><divclass="line">> cmake ../..</div><divclass="line">> make</div></div><!-- fragment --><p> This builds the library as a shared (dynamic) library (<code>.so</code> or <code>.dylib</code>), a static library (<code>.a</code>), and as a single object file (<code>.o</code>).</p>
<p><code>> sudo make install</code> (install the library and header files in <code>/usr/local/lib</code> and <code>/usr/local/include</code>)</p>
<p>You can build the debug version which does many internal checks and maintains detailed statistics as:</p>
<divclass="fragment"><divclass="line">> mkdir -p out/debug</div><divclass="line">> cd out/debug</div><divclass="line">> cmake -DCMAKE_BUILD_TYPE=Debug ../..</div><divclass="line">> make</div></div><!-- fragment --><p> This will name the shared library as <code>libmimalloc-debug.so</code>.</p>
<p>Finally, you can build a <em>secure</em> version that uses guard pages, encrypted free lists, etc, as: </p><divclass="fragment"><divclass="line">> mkdir -p out/secure</div><divclass="line">> cd out/secure</div><divclass="line">> cmake -DMI_SECURE=ON ../..</div><divclass="line">> make</div></div><!-- fragment --><p> This will name the shared library as <code>libmimalloc-secure.so</code>. Use <code>ccmake</code><sup>2</sup> instead of <code>cmake</code> to see and customize all the available build options.</p>
<divclass="textblock"><p>You can set further options either programmatically (using <ahref="https://microsoft.github.io/mimalloc/group__options.html"><code>mi_option_set</code></a>), or via environment variables.</p>
<ul>
<li><code>MIMALLOC_SHOW_STATS=1</code>: show statistics when the program terminates.</li>
<li><code>MIMALLOC_VERBOSE=1</code>: show verbose messages.</li>
<li><code>MIMALLOC_SHOW_ERRORS=1</code>: show error and warning messages.</li>
<li><code>MIMALLOC_PAGE_RESET=0</code>: by default, mimalloc will reset (or purge) OS pages when not in use to signal to the OS that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server) programs. By setting it to <code>0</code> no such page resets will be done which can improve performance for programs that are not long running. As an alternative, the <code>MIMALLOC_RESET_DELAY=</code><msecs> can be set higher (100ms by default) to make the page reset occur less frequently instead of turning it off completely.</li>
<li><code>MIMALLOC_LARGE_OS_PAGES=1</code>: use large OS pages (2MiB) when available; for some workloads this can significantly improve performance. Use <code>MIMALLOC_VERBOSE</code> to check if the large OS pages are enabled – usually one needs to explicitly allow large OS pages (as on <ahref="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <ahref="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>). However, sometimes the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that can have fragmented memory (for that reason, we generally recommend to use <code>MIMALLOC_RESERVE_HUGE_OS_PAGES</code> instead when possible).</li>
<li><code>MIMALLOC_RESERVE_HUGE_OS_PAGES=N</code>: where N is the number of 1GiB <em>huge</em> OS pages. This reserves the huge pages at startup and sometimes this can give a large (latency) performance improvement on big workloads. Usually it is better to not use <code>MIMALLOC_LARGE_OS_PAGES</code> in combination with this setting. Just like large OS pages, use with care as reserving contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at startup only once). Note that we usually need to explicitly enable huge OS pages (as on <ahref="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <ahref="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>)). With huge OS pages, it may be beneficial to set the setting <code>MIMALLOC_EAGER_COMMIT_DELAY=N</code> (<code>N</code> is 1 by default) to delay the initial <code>N</code> segments (of 4MiB) of a thread to not allocate in the huge OS pages; this prevents threads that are short lived and allocate just a little to take up space in the huge OS page area (which cannot be reset).</li>
</ul>
<p>Use caution when using <code>fork</code> in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write for all pages in the original process including the huge OS pages. When any memory is now written in that area, the OS will copy the entire 1GiB huge page (or 2MiB large page) which can cause the memory usage to grow in big increments. </p>
</div></div><!-- PageDoc -->
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<divid="nav-path"class="navpath"><!-- id is needed for treeview function! -->
<trclass="memdesc:ga5850da130c936bd77db039dcfbc8295d"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Allocate <em>size</em> bytes aligned by <em>alignment</em> at a specified <em>offset</em>. <ahref="#ga5850da130c936bd77db039dcfbc8295d">More...</a><br/></td></tr>
<p>Allocate <em>size</em> bytes aligned by <em>alignment</em>. </p>
<dlclass="params"><dt>Parameters</dt><dd>
<tableclass="params">
<tr><tdclass="paramname">size</td><td>number of bytes to allocate. </td></tr>
<tr><tdclass="paramname">alignment</td><td>the minimal alignment of the allocated memory. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd>pointer to the allocated memory or <em>NULL</em> if out of memory. The returned pointer is aligned by <em>alignment</em>, i.e. <code>(uintptr_t)p % alignment == 0</code>.</dd></dl>
<p>Returns a unique pointer if called with <em>size</em> 0. </p><dlclass="section see"><dt>See also</dt><dd><ahref="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-malloc?view=vs-2017">_aligned_malloc</a> (on Windows) </dd>
<dd>
<ahref="http://man.openbsd.org/reallocarray">aligned_alloc</a> (on BSD, with switched arguments!) </dd>
<dd>
<ahref="https://linux.die.net/man/3/posix_memalign">posix_memalign</a> (on Posix, with switched arguments!) </dd>
<dd>
<ahref="https://linux.die.net/man/3/posix_memalign">memalign</a> (on Linux, with switched arguments!) </dd></dl>
<p>Allocate <em>size</em> bytes aligned by <em>alignment</em> at a specified <em>offset</em>. </p>
<dlclass="params"><dt>Parameters</dt><dd>
<tableclass="params">
<tr><tdclass="paramname">size</td><td>number of bytes to allocate. </td></tr>
<tr><tdclass="paramname">alignment</td><td>the minimal alignment of the allocated memory at <em>offset</em>. </td></tr>
<tr><tdclass="paramname">offset</td><td>the offset that should be aligned. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd>pointer to the allocated memory or <em>NULL</em> if out of memory. The returned pointer is aligned by <em>alignment</em> at <em>offset</em>, i.e. <code>((uintptr_t)p + offset) % alignment == 0</code>.</dd></dl>
<p>Returns a unique pointer if called with <em>size</em> 0. </p><dlclass="section see"><dt>See also</dt><dd><ahref="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-offset-malloc?view=vs-2017">_aligned_offset_malloc</a> (on Windows) </dd></dl>
<trclass="memdesc:structmi__heap__area__t"><tdclass="mdescLeft"> </td><tdclass="mdescRight">An area of heap space contains blocks of a single size. <ahref="group__analysis.html#structmi__heap__area__t">More...</a><br/></td></tr>
<trclass="memdesc:gadfa01e2900f0e5d515ad5506b26f6d65"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Visitor function passed to <aclass="el"href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed"title="Visit all areas and blocks in a heap.">mi_heap_visit_blocks()</a><ahref="#gadfa01e2900f0e5d515ad5506b26f6d65">More...</a><br/></td></tr>
<trclass="memdesc:gaa862aa8ed8d57d84cae41fc1022d71af"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Does a heap contain a pointer to a previously allocated block? <ahref="#gaa862aa8ed8d57d84cae41fc1022d71af">More...</a><br/></td></tr>
<trclass="memdesc:ga0d67c1789faaa15ff366c024fcaf6377"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Check safely if any pointer is part of a heap. <ahref="#ga0d67c1789faaa15ff366c024fcaf6377">More...</a><br/></td></tr>
<trclass="memdesc:ga628c237489c2679af84a4d0d143b3dd5"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Check safely if any pointer is part of the default heap of this thread. <ahref="#ga628c237489c2679af84a4d0d143b3dd5">More...</a><br/></td></tr>
<trclass="memdesc:ga70c46687dc6e9dc98b232b02646f8bed"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Visit all areas and blocks in a heap. <ahref="#ga70c46687dc6e9dc98b232b02646f8bed">More...</a><br/></td></tr>
<p>Visitor function passed to <aclass="el"href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed"title="Visit all areas and blocks in a heap.">mi_heap_visit_blocks()</a></p>
<dlclass="section return"><dt>Returns</dt><dd><em>true</em> if ok, <em>false</em> to stop visiting (i.e. break)</dd></dl>
<p>This function is always first called for every <em>area</em> with <em>block</em> as a <em>NULL</em> pointer. If <em>visit_all_blocks</em> was <em>true</em>, the function is then called for every allocated block in that area. </p>
<p>Check safely if any pointer is part of the default heap of this thread. </p>
<dlclass="params"><dt>Parameters</dt><dd>
<tableclass="params">
<tr><tdclass="paramname">p</td><td>Any pointer – not required to be previously allocated by us. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd><em>true</em> if <em>p</em> points to a block in default heap of this thread.</dd></dl>
<p>Note: expensive function, linear in the pages in the heap. </p><dlclass="section see"><dt>See also</dt><dd><aclass="el"href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af"title="Does a heap contain a pointer to a previously allocated block?">mi_heap_contains_block()</a></dd>
<dd>
<aclass="el"href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05"title="Get the default heap that is used for mi_malloc() et al.">mi_heap_get_default()</a></dd></dl>
<tr><tdclass="paramname">p</td><td>Any pointer – not required to be previously allocated by us. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd><em>true</em> if <em>p</em> points to a block in <em>heap</em>.</dd></dl>
<p>Note: expensive function, linear in the pages in the heap. </p><dlclass="section see"><dt>See also</dt><dd><aclass="el"href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af"title="Does a heap contain a pointer to a previously allocated block?">mi_heap_contains_block()</a></dd>
<dd>
<aclass="el"href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05"title="Get the default heap that is used for mi_malloc() et al.">mi_heap_get_default()</a></dd></dl>
<tr><tdclass="paramname">p</td><td>Pointer to a previously allocated block (in any heap)– cannot be some random pointer! </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd><em>true</em> if the block pointed to by <em>p</em> is in the <em>heap</em>. </dd></dl>
<dlclass="section see"><dt>See also</dt><dd><aclass="el"href="group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377"title="Check safely if any pointer is part of a heap.">mi_heap_check_owned()</a></dd></dl>
<tr><tdclass="paramname">heap</td><td>The heap to visit. </td></tr>
<tr><tdclass="paramname">visit_all_blocks</td><td>If <em>true</em> visits all allocated blocks, otherwise <em>visitor</em> is only called for every heap area. </td></tr>
<tr><tdclass="paramname">visitor</td><td>This function is called for every area in the heap (with <em>block</em> as <em>NULL</em>). If <em>visit_all_blocks</em> is <em>true</em>, <em>visitor</em> is also called for every allocated block in every area (with <code>block!=NULL</code>). return <em>false</em> from this function to stop visiting early. </td></tr>
<tr><tdclass="paramname">arg</td><td>Extra argument passed to <em>visitor</em>. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd><em>true</em> if all areas and blocks were visited. </dd></dl>
</div>
</div>
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<divid="nav-path"class="navpath"><!-- id is needed for treeview function! -->
<p><code>mi_</code> prefixed implementations of various allocation functions that use C++ semantics on out-of-memory, generally calling <code>std::get_new_handler</code> and raising a <code>std::bad_alloc</code> exception on failure.
<trclass="memitem:structmi__stl__allocator"><tdclass="memItemLeft"align="right"valign="top">struct  </td><tdclass="memItemRight"valign="bottom"><aclass="el"href="group__cpp.html#structmi__stl__allocator">mi_stl_allocator< T ></a></td></tr>
<trclass="memdesc:structmi__stl__allocator"><tdclass="mdescLeft"> </td><tdclass="mdescRight"><em>std::allocator</em> implementation for mimalloc for use in STL containers. <ahref="group__cpp.html#structmi__stl__allocator">More...</a><br/></td></tr>
<trclass="memdesc:gaad048a9fce3d02c5909cd05c6ec24545"><tdclass="mdescLeft"> </td><tdclass="mdescRight">like <aclass="el"href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a"title="Allocate size bytes.">mi_malloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <ahref="#gaad048a9fce3d02c5909cd05c6ec24545">More...</a><br/></td></tr>
<trclass="memdesc:gae7bc4f56cd57ed3359060ff4f38bda81"><tdclass="mdescLeft"> </td><tdclass="mdescRight">like <aclass="el"href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6"title="Allocate count elements of size bytes.">mi_mallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <ahref="#gae7bc4f56cd57ed3359060ff4f38bda81">More...</a><br/></td></tr>
<trclass="memitem:gaef2c2bdb4f70857902d3c8903ac095f3"><tdclass="memItemLeft"align="right"valign="top">void * </td><tdclass="memItemRight"valign="bottom"><aclass="el"href="group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3">mi_new_aligned</a> (std::size_t n, std::align_val_t alignment) noexcept(false)</td></tr>
<trclass="memdesc:gaef2c2bdb4f70857902d3c8903ac095f3"><tdclass="mdescLeft"> </td><tdclass="mdescRight">like <aclass="el"href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56"title="Allocate size bytes aligned by alignment.">mi_malloc_aligned()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <ahref="#gaef2c2bdb4f70857902d3c8903ac095f3">More...</a><br/></td></tr>
<trclass="memdesc:gaeaded64eda71ed6b1d569d3e723abc4a"><tdclass="mdescLeft"> </td><tdclass="mdescRight">like <code>mi_malloc</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure. <ahref="#gaeaded64eda71ed6b1d569d3e723abc4a">More...</a><br/></td></tr>
<trclass="memitem:gab5e29558926d934c3f1cae8c815f942c"><tdclass="memItemLeft"align="right"valign="top">void * </td><tdclass="memItemRight"valign="bottom"><aclass="el"href="group__cpp.html#gab5e29558926d934c3f1cae8c815f942c">mi_new_aligned_nothrow</a> (size_t n, size_t alignment)</td></tr>
<trclass="memdesc:gab5e29558926d934c3f1cae8c815f942c"><tdclass="mdescLeft"> </td><tdclass="mdescRight">like <code>mi_malloc_aligned</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure. <ahref="#gab5e29558926d934c3f1cae8c815f942c">More...</a><br/></td></tr>
<trclass="memdesc:gaab78a32f55149e9fbf432d5288e38e1e"><tdclass="mdescLeft"> </td><tdclass="mdescRight">like <aclass="el"href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6"title="Re-allocate memory to newsize bytes.">mi_realloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <ahref="#gaab78a32f55149e9fbf432d5288e38e1e">More...</a><br/></td></tr>
<trclass="memdesc:ga756f4b2bc6a7ecd0a90baea8e90c7907"><tdclass="mdescLeft"> </td><tdclass="mdescRight">like <aclass="el"href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853"title="Re-allocate memory to count elements of size bytes.">mi_reallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <ahref="#ga756f4b2bc6a7ecd0a90baea8e90c7907">More...</a><br/></td></tr>
<p><code>mi_</code> prefixed implementations of various allocation functions that use C++ semantics on out-of-memory, generally calling <code>std::get_new_handler</code> and raising a <code>std::bad_alloc</code> exception on failure. </p>
<p>Note: use the <code>mimalloc-new-delete.h</code> header to override the <em>new</em> and <em>delete</em> operators globally. The wrappers here are mostly for convience for library writers that need to interface with mimalloc from C++. </p>
<p>like <aclass="el"href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a"title="Allocate size bytes.">mi_malloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
<p>like <aclass="el"href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56"title="Allocate size bytes aligned by alignment.">mi_malloc_aligned()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
<p>like <aclass="el"href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6"title="Allocate count elements of size bytes.">mi_mallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
<p>like <aclass="el"href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6"title="Re-allocate memory to newsize bytes.">mi_realloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
<p>like <aclass="el"href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853"title="Re-allocate memory to count elements of size bytes.">mi_reallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
</div>
</div>
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<divid="nav-path"class="navpath"><!-- id is needed for treeview function! -->
<trclass="memdesc:ga1ea64283508718d9d645c38efc2f4305"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Maximum size allowed for small allocations in <aclass="el"href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99"title="Allocate a small object.">mi_malloc_small</a> and <aclass="el"href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152"title="Allocate a zero initialized small object.">mi_zalloc_small</a> (usually <code>128*sizeof(void*)</code> (= 1KB on 64-bit systems)) <ahref="#ga1ea64283508718d9d645c38efc2f4305">More...</a><br/></td></tr>
<trclass="memitem:ga299dae78d25ce112e384a98b7309c5be"><tdclass="memItemLeft"align="right"valign="top">typedef void() </td><tdclass="memItemRight"valign="bottom"><aclass="el"href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a>(bool force, unsigned long long heartbeat, void *arg)</td></tr>
<trclass="memdesc:ga299dae78d25ce112e384a98b7309c5be"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Type of deferred free functions. <ahref="#ga299dae78d25ce112e384a98b7309c5be">More...</a><br/></td></tr>
<trclass="memdesc:gad823d23444a4b77a40f66bf075a98a0c"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Type of output functions. <ahref="#gad823d23444a4b77a40f66bf075a98a0c">More...</a><br/></td></tr>
<trclass="memdesc:ga7136c2e55cb22c98ecf95d08d6debb99"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Allocate a small object. <ahref="#ga7136c2e55cb22c98ecf95d08d6debb99">More...</a><br/></td></tr>
<trclass="memdesc:ga220f29f40a44404b0061c15bc1c31152"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Allocate a zero initialized small object. <ahref="#ga220f29f40a44404b0061c15bc1c31152">More...</a><br/></td></tr>
<trclass="memdesc:ga089c859d9eddc5f9b4bd946cd53cebee"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Return the available bytes in a memory block. <ahref="#ga089c859d9eddc5f9b4bd946cd53cebee">More...</a><br/></td></tr>
<trclass="memdesc:gac057927cd06c854b45fe7847e921bd47"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Return the used allocation size. <ahref="#gac057927cd06c854b45fe7847e921bd47">More...</a><br/></td></tr>
<trclass="memdesc:ga537f13b299ddf801e49a5a94fde02c79"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Print the main statistics. <ahref="#ga537f13b299ddf801e49a5a94fde02c79">More...</a><br/></td></tr>
<trclass="memdesc:ga854b1de8cb067c7316286c28b2fcd3d1"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Merge thread local statistics with the main statistics and reset. <ahref="#ga854b1de8cb067c7316286c28b2fcd3d1">More...</a><br/></td></tr>
<trclass="memdesc:gaf8e73efc2cbca9ebfdfb166983a04c17"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Initialize mimalloc on a thread. <ahref="#gaf8e73efc2cbca9ebfdfb166983a04c17">More...</a><br/></td></tr>
<trclass="memdesc:ga0ae4581e85453456a0d658b2b98bf7bf"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Uninitialize mimalloc on a thread. <ahref="#ga0ae4581e85453456a0d658b2b98bf7bf">More...</a><br/></td></tr>
<trclass="memdesc:gab1dac8476c46cb9eecab767eb40c1525"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Print out heap statistics for this thread. <ahref="#gab1dac8476c46cb9eecab767eb40c1525">More...</a><br/></td></tr>
<trclass="memdesc:gae5b17ff027cd2150b43a33040250cf3f"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Register an output function. <ahref="#gae5b17ff027cd2150b43a33040250cf3f">More...</a><br/></td></tr>
<trclass="memdesc:ga5f071b10d4df1c3658e04e7fd67a94e6"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Is a pointer part of our heap? <ahref="#ga5f071b10d4df1c3658e04e7fd67a94e6">More...</a><br/></td></tr>
<trclass="memdesc:ga3132f521fb756fc0e8ec0b74fb58df50"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Reserve <em>pages</em> of huge OS pages (1GiB) evenly divided over <em>numa_nodes</em> nodes, but stops after at most <code>timeout_msecs</code> seconds. <ahref="#ga3132f521fb756fc0e8ec0b74fb58df50">More...</a><br/></td></tr>
<trclass="memitem:ga7795a13d20087447281858d2c771cca1"><tdclass="memItemLeft"align="right"valign="top">int </td><tdclass="memItemRight"valign="bottom"><aclass="el"href="group__extended.html#ga7795a13d20087447281858d2c771cca1">mi_reserve_huge_os_pages_at</a> (size_t pages, int numa_node, size_t timeout_msecs)</td></tr>
<trclass="memdesc:ga7795a13d20087447281858d2c771cca1"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Reserve <em>pages</em> of huge OS pages (1GiB) at a specific <em>numa_node</em>, but stops after at most <code>timeout_msecs</code> seconds. <ahref="#ga7795a13d20087447281858d2c771cca1">More...</a><br/></td></tr>
<trclass="memdesc:gaad25050b19f30cd79397b227e0157a3f"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Is the C runtime <em>malloc</em> API redirected? <ahref="#gaad25050b19f30cd79397b227e0157a3f">More...</a><br/></td></tr>
<trclass="memdesc:ga7d862c2affd5790381da14eb102a364d"><tdclass="mdescLeft"> </td><tdclass="mdescRight">Return process information (time and memory usage). <ahref="#ga7d862c2affd5790381da14eb102a364d">More...</a><br/></td></tr>
<p>Maximum size allowed for small allocations in <aclass="el"href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99"title="Allocate a small object.">mi_malloc_small</a> and <aclass="el"href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152"title="Allocate a zero initialized small object.">mi_zalloc_small</a> (usually <code>128*sizeof(void*)</code> (= 1KB on 64-bit systems)) </p>
<tr><tdclass="paramname">err</td><td>Error code (see <aclass="el"href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45"title="Register an error callback function.">mi_register_error()</a> for a complete list). </td></tr>
<tr><tdclass="paramname">arg</td><td>Argument that was passed at registration to hold extra state.</td></tr>
</table>
</dd>
</dl>
<dlclass="section see"><dt>See also</dt><dd><aclass="el"href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45"title="Register an error callback function.">mi_register_error()</a></dd></dl>
<tr><tdclass="paramname">force</td><td>If <em>true</em>, aggressively return memory to the OS (can be expensive!)</td></tr>
</table>
</dd>
</dl>
<p>Regular code should not have to call this function. It can be beneficial in very narrow circumstances; in particular, when a long running thread allocates a lot of blocks that are freed by other threads it may improve resource usage by calling this every once in a while. </p>
<tr><tdclass="paramname">size</td><td>The minimal required size in bytes. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd>the size <code>n</code> that will be allocated, where <code>n >= size</code>.</dd></dl>
<p>Generally, <code>mi_usable_size(mi_malloc(size)) == mi_good_size(size)</code>. This can be used to reduce internal wasted space when allocating buffers for example.</p>
<dlclass="section see"><dt>See also</dt><dd><aclass="el"href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee"title="Return the available bytes in a memory block.">mi_usable_size()</a></dd></dl>
<tr><tdclass="paramname">size</td><td>The size in bytes, can be at most <aclass="el"href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305"title="Maximum size allowed for small allocations in mi_malloc_small and mi_zalloc_small (usually 128*sizeof...">MI_SMALL_SIZE_MAX</a>. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd>a pointer to newly allocated memory of at least <em>size</em> bytes, or <em>NULL</em> if out of memory. This function is meant for use in run-time systems for best performance and does not check if <em>size</em> was indeed small – use with care! </dd></dl>
<p>Return process information (time and memory usage). </p>
<dlclass="params"><dt>Parameters</dt><dd>
<tableclass="params">
<tr><tdclass="paramname">elapsed_msecs</td><td>Optional. Elapsed wall-clock time of the process in milli-seconds. </td></tr>
<tr><tdclass="paramname">user_msecs</td><td>Optional. User time in milli-seconds (as the sum over all threads). </td></tr>
<tr><tdclass="paramname">system_msecs</td><td>Optional. System time in milli-seconds. </td></tr>
<tr><tdclass="paramname">current_rss</td><td>Optional. Current working set size (touched pages). </td></tr>
<tr><tdclass="paramname">peak_rss</td><td>Optional. Peak working set size (touched pages). </td></tr>
<tr><tdclass="paramname">current_commit</td><td>Optional. Current committed memory (backed by the page file). </td></tr>
<tr><tdclass="paramname">peak_commit</td><td>Optional. Peak committed memory (backed by the page file). </td></tr>
<tr><tdclass="paramname">page_faults</td><td>Optional. Count of hard page faults.</td></tr>
</table>
</dd>
</dl>
<p>The <em>current_rss</em> is precise on Windows and MacOSX; other systems estimate this using <em>current_commit</em>. The <em>commit</em> is precise on Windows but estimated on other systems as the amount of read/write accessible memory reserved by mimalloc. </p>
<tr><tdclass="paramname">deferred_free</td><td>Address of a deferred free-ing function or <em>NULL</em> to unregister. </td></tr>
<tr><tdclass="paramname">arg</td><td>Argument that will be passed on to the deferred free function.</td></tr>
</table>
</dd>
</dl>
<p>Some runtime systems use deferred free-ing, for example when using reference counting to limit the worst case free time. Such systems can register (re-entrant) deferred free function to free more memory on demand. When the <em>force</em> parameter is <em>true</em> all possible memory should be freed. The per-thread <em>heartbeat</em> parameter is monotonically increasing and guaranteed to be deterministic if the program allocates deterministically. The <em>deferred_free</em> function is guaranteed to be called deterministically after some number of allocations (regardless of freeing or available free memory). At most one <em>deferred_free</em> function can be active. </p>
<tr><tdclass="paramname">errfun</td><td>The error function that is called on an error (use <em>NULL</em> for default) </td></tr>
<tr><tdclass="paramname">arg</td><td>Extra argument that will be passed on to the error function.</td></tr>
</table>
</dd>
</dl>
<p>The <em>errfun</em> function is called on an error in mimalloc after emitting an error message (through the output function). It as always legal to just return from the <em>errfun</em> function in which case allocation functions generally return <em>NULL</em> or ignore the condition. The default function only calls abort() when compiled in secure mode with an <em>EFAULT</em> error. The possible error codes are:</p><ul>
<li><em>EAGAIN:</em> Double free was detected (only in debug and secure mode).</li>
<li><em>EFAULT:</em> Corrupted free list or meta-data was detected (only in debug and secure mode).</li>
<li><em>ENOMEM:</em> Not enough memory available to satisfy the request.</li>
<li><em>EOVERFLOW:</em> Too large a request, for example in <aclass="el"href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d"title="Allocate zero-initialized count elements of size bytes.">mi_calloc()</a>, the <em>count</em> and <em>size</em> parameters are too large.</li>
<li><em>EINVAL:</em> Trying to free or re-allocate an invalid pointer. </li>
<p>Reserve <em>pages</em> of huge OS pages (1GiB) at a specific <em>numa_node</em>, but stops after at most <code>timeout_msecs</code> seconds. </p>
<dlclass="params"><dt>Parameters</dt><dd>
<tableclass="params">
<tr><tdclass="paramname">pages</td><td>The number of 1GiB pages to reserve. </td></tr>
<tr><tdclass="paramname">numa_node</td><td>The NUMA node where the memory is reserved (start at 0). </td></tr>
<tr><tdclass="paramname">timeout_msecs</td><td>Maximum number of milli-seconds to try reserving, or 0 for no timeout. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd>0 if successfull, <em>ENOMEM</em> if running out of memory, or <em>ETIMEDOUT</em> if timed out.</dd></dl>
<p>The reserved memory is used by mimalloc to satisfy allocations. May quit before <em>timeout_msecs</em> are expired if it estimates it will take more than 1.5 times <em>timeout_msecs</em>. The time limit is needed because on some operating systems it can take a long time to reserve contiguous memory if the physical memory is fragmented. </p>
<p>Reserve <em>pages</em> of huge OS pages (1GiB) evenly divided over <em>numa_nodes</em> nodes, but stops after at most <code>timeout_msecs</code> seconds. </p>
<dlclass="params"><dt>Parameters</dt><dd>
<tableclass="params">
<tr><tdclass="paramname">pages</td><td>The number of 1GiB pages to reserve. </td></tr>
<tr><tdclass="paramname">numa_nodes</td><td>The number of nodes do evenly divide the pages over, or 0 for using the actual number of NUMA nodes. </td></tr>
<tr><tdclass="paramname">timeout_msecs</td><td>Maximum number of milli-seconds to try reserving, or 0 for no timeout. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd>0 if successfull, <em>ENOMEM</em> if running out of memory, or <em>ETIMEDOUT</em> if timed out.</dd></dl>
<p>The reserved memory is used by mimalloc to satisfy allocations. May quit before <em>timeout_msecs</em> are expired if it estimates it will take more than 1.5 times <em>timeout_msecs</em>. The time limit is needed because on some operating systems it can take a long time to reserve contiguous memory if the physical memory is fragmented. </p>
<p>Should not be used as on most systems (pthreads, windows) this is done automatically. Ensures that any memory that is not freed yet (but will be freed by other threads in the future) is properly handled. </p>
<p>Return the available bytes in a memory block. </p>
<dlclass="params"><dt>Parameters</dt><dd>
<tableclass="params">
<tr><tdclass="paramname">p</td><td>Pointer to previously allocated memory (or <em>NULL</em>) </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd>Returns the available bytes in the memory block, or 0 if <em>p</em> was <em>NULL</em>.</dd></dl>
<p>The returned size can be used to call <em>mi_expand</em> successfully. The returned size is always at least equal to the allocated size of <em>p</em>, and, in the current design, should be less than 16.7% more.</p>
<tr><tdclass="paramname">size</td><td>The size in bytes, can be at most <aclass="el"href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305"title="Maximum size allowed for small allocations in mi_malloc_small and mi_zalloc_small (usually 128*sizeof...">MI_SMALL_SIZE_MAX</a>. </td></tr>
</table>
</dd>
</dl>
<dlclass="section return"><dt>Returns</dt><dd>a pointer to newly allocated zero-initialized memory of at least <em>size</em> bytes, or <em>NULL</em> if out of memory. This function is meant for use in run-time systems for best performance and does not check if <em>size</em> was indeed small – use with care! </dd></dl>
</div>
</div>
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<divid="nav-path"class="navpath"><!-- id is needed for treeview function! -->
Loaded 100 of 3067 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.