tangled
alpha
login
or
join now
pyrox.dev
/
nixpkgs
lol
0
fork
atom
overview
issues
pulls
pipelines
qemu: Add binfmt preserve-argv[0] wrapper
Zhaofeng Li
4 years ago
3011531c
34ad3ffe
+112
3 changed files
expand all
collapse all
unified
split
pkgs
applications
virtualization
qemu
binfmt-p-wrapper.c
binfmt-p-wrapper.nix
top-level
all-packages.nix
+79
pkgs/applications/virtualization/qemu/binfmt-p-wrapper.c
···
1
1
+
// This is a tiny wrapper that converts the extra arv[0] argument
2
2
+
// from binfmt-misc with the P flag enabled to QEMU parameters.
3
3
+
// It also prevents LD_* environment variables from being applied
4
4
+
// to QEMU itself.
5
5
+
6
6
+
#include <stdio.h>
7
7
+
#include <stdlib.h>
8
8
+
#include <string.h>
9
9
+
#include <unistd.h>
10
10
+
11
11
+
#ifndef TARGET_QEMU
12
12
+
#error "Define TARGET_QEMU to be the path to the qemu-user binary (e.g., -DTARGET_QEMU=\"/full/path/to/qemu-riscv64\")"
13
13
+
#endif
14
14
+
15
15
+
extern char **environ;
16
16
+
17
17
+
int main(int argc, char *argv[]) {
18
18
+
if (argc < 3) {
19
19
+
fprintf(stderr, "%s: This should be run as the binfmt interpreter with the P flag\n", argv[0]);
20
20
+
fprintf(stderr, "%s: My preconfigured qemu-user binary: %s\n", argv[0], TARGET_QEMU);
21
21
+
return 1;
22
22
+
}
23
23
+
24
24
+
size_t environ_count = 0;
25
25
+
for (char **cur = environ; *cur != NULL; ++cur) {
26
26
+
environ_count++;
27
27
+
}
28
28
+
29
29
+
size_t new_argc = 3;
30
30
+
size_t new_argv_alloc = argc + 2 * environ_count + 2; // [ "-E", env ] for each LD_* env + [ "-0", argv0 ]
31
31
+
char **new_argv = (char**)malloc((new_argv_alloc + 1) * sizeof(char*));
32
32
+
if (!new_argv) {
33
33
+
fprintf(stderr, "FATAL: Failed to allocate new argv array\n");
34
34
+
abort();
35
35
+
}
36
36
+
37
37
+
new_argv[0] = TARGET_QEMU;
38
38
+
new_argv[1] = "-0";
39
39
+
new_argv[2] = argv[2];
40
40
+
41
41
+
// Pass all LD_ env variables as -E and strip them in `new_environ`
42
42
+
size_t new_environc = 0;
43
43
+
char **new_environ = (char**)malloc((environ_count + 1) * sizeof(char*));
44
44
+
if (!new_environ) {
45
45
+
fprintf(stderr, "FATAL: Failed to allocate new environ array\n");
46
46
+
abort();
47
47
+
}
48
48
+
49
49
+
for (char **cur = environ; *cur != NULL; ++cur) {
50
50
+
if (strncmp("LD_", *cur, 3) == 0) {
51
51
+
new_argv[new_argc++] = "-E";
52
52
+
new_argv[new_argc++] = *cur;
53
53
+
} else {
54
54
+
new_environ[new_environc++] = *cur;
55
55
+
}
56
56
+
}
57
57
+
new_environ[new_environc] = NULL;
58
58
+
59
59
+
size_t new_arg_start = new_argc;
60
60
+
new_argc += argc - 3 + 2; // [ "--", full_binary_path ]
61
61
+
62
62
+
if (argc > 3) {
63
63
+
memcpy(&new_argv[new_arg_start + 2], &argv[3], (argc - 3) * sizeof(char**));
64
64
+
}
65
65
+
66
66
+
new_argv[new_arg_start] = "--";
67
67
+
new_argv[new_arg_start + 1] = argv[1];
68
68
+
new_argv[new_argc] = NULL;
69
69
+
70
70
+
#ifdef DEBUG
71
71
+
for (size_t i = 0; i < new_argc; ++i) {
72
72
+
fprintf(stderr, "argv[%zu] = %s\n", i, new_argv[i]);
73
73
+
}
74
74
+
#endif
75
75
+
76
76
+
return execve(new_argv[0], new_argv, new_environ);
77
77
+
}
78
78
+
79
79
+
// vim: et:ts=4:sw=4
+31
pkgs/applications/virtualization/qemu/binfmt-p-wrapper.nix
···
1
1
+
# binfmt preserve-argv[0] wrapper
2
2
+
#
3
3
+
# More details in binfmt-p-wrapper.c
4
4
+
#
5
5
+
# The wrapper has to be static so LD_* environment variables
6
6
+
# cannot affect the execution of the wrapper itself.
7
7
+
8
8
+
{ lib, stdenv, pkgsStatic, enableDebug ? false }:
9
9
+
10
10
+
name: emulator:
11
11
+
12
12
+
pkgsStatic.stdenv.mkDerivation {
13
13
+
inherit name;
14
14
+
15
15
+
src = ./binfmt-p-wrapper.c;
16
16
+
17
17
+
dontUnpack = true;
18
18
+
dontInstall = true;
19
19
+
20
20
+
buildPhase = ''
21
21
+
runHook preBuild
22
22
+
23
23
+
mkdir -p $out/bin
24
24
+
$CC -o $out/bin/${name} -static -std=c99 -O2 \
25
25
+
-DTARGET_QEMU=\"${emulator}\" \
26
26
+
${lib.optionalString enableDebug "-DDEBUG"} \
27
27
+
$src
28
28
+
29
29
+
runHook postBuild
30
30
+
'';
31
31
+
}
+2
pkgs/top-level/all-packages.nix
···
27324
27324
27325
27325
qemu-utils = callPackage ../applications/virtualization/qemu/utils.nix {};
27326
27326
27327
27327
+
wrapQemuBinfmtP = callPackage ../applications/virtualization/qemu/binfmt-p-wrapper.nix { };
27328
27328
+
27327
27329
qgis-unwrapped = libsForQt5.callPackage ../applications/gis/qgis/unwrapped.nix {
27328
27330
withGrass = false;
27329
27331
};