Skip to content

Commit

Permalink
Make -run to intercept not only ld but also ld.lld and ld.gold
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed May 20, 2021
1 parent a856d55 commit 02e6c6a
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 12 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ command. It is sometimes very hard to pass an appropriate command line
option to `cc` to specify an alternative linker.

To deal with the situation, mold has a feature to intercept all
invocations of `/usr/bin/ld` and redirect it to itself. To use the
feature, run `make` (or other build command) as a subcommand of mold
as follows:
invocations of `/usr/bin/ld`, `/usr/bin/ld.lld` or `/usr/bin/ld.gold`
and redirect it to itself. To use the feature, run `make` (or other
build command) as a subcommand of mold as follows:

```
$ path/to/mold -run make <make-options-if-any>
Expand All @@ -96,7 +96,8 @@ $ path/to/mold -run make <make-options-if-any>
Internally, mold invokes a given command with `LD_PRELOAD` environment
variable set to its companion shared object file. The shared object
file intercepts all function calls to exec-family functions to replace
`argv[0]` with `mold` if it is `/usr/bin/ld`.
`argv[0]` with `mold` if it is `/usr/bin/ld`, `/usr/bin/ld.gold` or
`/usr/bin/ld.lld`.

Alternatively, you can pass `-fuse-ld=<absolute-path-to-mold-executable>`
to a linker command line. Since GCC doesn't support that option,
Expand Down
6 changes: 3 additions & 3 deletions docs/mold.1
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ build\fR) as follows:
.PP
If you run a build command like above, the command runs under the
influence of \fBmold\fR so that when the command tries to run
\fB/usr/bin/ld\fR, \fBmold\fR is silently invoked instead.
\fB/usr/bin/ld\fR, \fB/usr/bin/ld.gold\fR or \fB/usr/bin/ld.lld\fR,
\fBmold\fR is silently invoked instead.
.PP
Internally, \fBmold\fR invokes a given command with the
\fBLD_PRELOAD\fR environment variable set to its companion shared
object file. The shared object file intercepts all \fBexec()\fR-family
functions to run \fBmold\fR if \fB/usr/bin/ld\fR is attempted to be
run.
functions to run \fBmold\fR if other linker is attempted to be run.
.PP
If you don't want to use the \fB\-run\fR option, and if you are using
\fBclang\fR, you can pass \fB\-fuse\-ld\fR=\fI/absolute/path/to/mold\fR to
Expand Down
13 changes: 10 additions & 3 deletions mold-wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <dlfcn.h>
#include <spawn.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -39,10 +40,16 @@ static void get_args(va_list ap, int argc, char **argv) {
}
}

static bool is_ld(const char *path) {
return !strcmp(path, "/usr/bin/ld") ||
!strcmp(path, "/usr/bin/ld.lld") ||
!strcmp(path, "/usr/bin/ld.gold");
}

int execve(const char *path, char *const *argv, char *const *envp) {
debug_print("execve %s\n", path);

if (!strcmp(path, "/usr/bin/ld")) {
if (is_ld(path)) {
path = get_mold_path();
((const char **)argv)[0] = path;
}
Expand Down Expand Up @@ -87,7 +94,7 @@ int execvp(const char *file, char *const *argv) {
int execvpe(const char *file, char *const *argv, char *const *envp) {
debug_print("execvpe %s\n", file);

if (!strcmp(file, "ld") || !strcmp(file, "/usr/bin/ld")) {
if (!strcmp(file, "ld") || is_ld(file)) {
file = get_mold_path();
((const char **)argv)[0] = file;
}
Expand All @@ -102,7 +109,7 @@ int posix_spawn(pid_t *pid, const char *path,
char *const *argv, char *const *envp) {
debug_print("posix_spawn %s\n", path);

if (!strcmp(path, "/usr/bin/ld")) {
if (is_ld(path)) {
path = get_mold_path();
((const char **)argv)[0] = path;
}
Expand Down
6 changes: 4 additions & 2 deletions subprocess.cc
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,10 @@ void process_run_subcommand(Context<E> &ctx, int argc, char **argv) {
putenv(strdup(("LD_PRELOAD=" + dso_path).c_str()));
putenv(strdup(("MOLD_REAL_PATH=" + self).c_str()));

// If /usr/bin/ld is specified, run mold itself
if (std::string_view cmd = argv[2]; cmd == "ld" || cmd == "/usr/bin/ld") {
// If /usr/bin/ld{,lld,gold} is specified, run mold itself
if (std::string_view cmd = argv[2]; cmd == "ld" ||
cmd == "/usr/bin/ld" || cmd == "/usr/bin/ld.lld" ||
cmd == "/usr/bin/ld.gold") {
execv(self.c_str(), argv + 2);
Fatal(ctx) << "mold -run failed: " << self << ": " << strerror(errno);
}
Expand Down
2 changes: 2 additions & 0 deletions test/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@ grep -q mold $t/log
../mold -run env | grep -q '^MOLD_REAL_PATH=.*/mold$'

../mold -run /usr/bin/ld --version | grep -q mold
../mold -run /usr/bin/ld.lld --version | grep -q mold
../mold -run /usr/bin/ld.gold --version | grep -q mold

echo OK

0 comments on commit 02e6c6a

Please sign in to comment.