authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-09 14:23:57+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log9487007ffe332affe3960a5cca6c87759ffdfd22
tree74c7d3796643c2b96a0b0c263d5092537751ccc2
parent1efc0519ce711ba8e7ee4d621a5bd13766c23020

elf: port more linker tests


1 files changed, 518 insertions(+), 0 deletions(-)

test/link/elf.zig+518
......@@ -27,6 +27,8 @@ pub fn build(b: *Build) void {
2727 elf_step.dependOn(testEmptyObject(b, .{ .target = musl_target }));
2828 elf_step.dependOn(testEntryPoint(b, .{ .target = musl_target }));
2929 elf_step.dependOn(testGcSections(b, .{ .target = musl_target }));
30 elf_step.dependOn(testImageBase(b, .{ .target = musl_target }));
31 elf_step.dependOn(testInitArrayOrder(b, .{ .target = musl_target }));
3032 elf_step.dependOn(testLinkingC(b, .{ .target = musl_target }));
3133 elf_step.dependOn(testLinkingCpp(b, .{ .target = musl_target }));
3234 elf_step.dependOn(testLinkingZig(b, .{ .target = musl_target }));
......@@ -44,8 +46,24 @@ pub fn build(b: *Build) void {
4446 elf_step.dependOn(testDsoUndef(b, .{ .target = glibc_target }));
4547 elf_step.dependOn(testExportDynamic(b, .{ .target = glibc_target }));
4648 elf_step.dependOn(testExportSymbolsFromExe(b, .{ .target = glibc_target }));
49 // https://github.com/ziglang/zig/issues/17430
50 // elf_step.dependOn(testFuncAddress(b, .{ .target = glibc_target }));
51 elf_step.dependOn(testHiddenWeakUndef(b, .{ .target = glibc_target }));
52 elf_step.dependOn(testIFuncAlias(b, .{ .target = glibc_target }));
53 // https://github.com/ziglang/zig/issues/17430
54 // elf_step.dependOn(testIFuncDlopen(b, .{ .target = glibc_target }));
55 elf_step.dependOn(testIFuncDso(b, .{ .target = glibc_target }));
56 elf_step.dependOn(testIFuncDynamic(b, .{ .target = glibc_target }));
57 elf_step.dependOn(testIFuncExport(b, .{ .target = glibc_target }));
58 elf_step.dependOn(testIFuncFuncPtr(b, .{ .target = glibc_target }));
59 elf_step.dependOn(testIFuncNoPlt(b, .{ .target = glibc_target }));
60 // https://github.com/ziglang/zig/issues/17430 ??
61 // elf_step.dependOn(testIFuncStatic(b, .{ .target = glibc_target }));
62 // elf_step.dependOn(testIFuncStaticPie(b, .{ .target = glibc_target }));
63 elf_step.dependOn(testInitArrayOrder(b, .{ .target = glibc_target }));
4764 elf_step.dependOn(testLargeAlignmentDso(b, .{ .target = glibc_target }));
4865 elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = glibc_target }));
66 elf_step.dependOn(testPie(b, .{ .target = glibc_target }));
4967}
5068
5169fn testAbsSymbols(b: *Build, opts: Options) *Step {
......@@ -686,6 +704,32 @@ fn testExportSymbolsFromExe(b: *Build, opts: Options) *Step {
686704 return test_step;
687705}
688706
707fn testFuncAddress(b: *Build, opts: Options) *Step {
708 const test_step = addTestStep(b, "func-address", opts);
709
710 const dso = addSharedLibrary(b, "a", opts);
711 addCSourceBytes(dso, "void fn() {}", &.{});
712
713 const exe = addExecutable(b, "main", opts);
714 addCSourceBytes(exe,
715 \\#include <assert.h>
716 \\typedef void Func();
717 \\void fn();
718 \\Func *const ptr = fn;
719 \\int main() {
720 \\ assert(fn == ptr);
721 \\}
722 , &.{});
723 exe.linkLibrary(dso);
724 exe.force_pic = false;
725 exe.pie = false;
726
727 const run = addRunArtifact(exe);
728 test_step.dependOn(&run.step);
729
730 return test_step;
731}
732
689733fn testGcSections(b: *Build, opts: Options) *Step {
690734 const test_step = addTestStep(b, "gc-sections", opts);
691735
......@@ -776,6 +820,449 @@ fn testGcSections(b: *Build, opts: Options) *Step {
776820 return test_step;
777821}
778822
823fn testHiddenWeakUndef(b: *Build, opts: Options) *Step {
824 const test_step = addTestStep(b, "hidden-weak-undef", opts);
825
826 const dso = addSharedLibrary(b, "a", opts);
827 addCSourceBytes(dso,
828 \\__attribute__((weak, visibility("hidden"))) void foo();
829 \\void bar() { foo(); }
830 , &.{});
831
832 const check = dso.checkObject();
833 check.checkInDynamicSymtab();
834 check.checkNotPresent("foo");
835 check.checkInDynamicSymtab();
836 check.checkContains("bar");
837 test_step.dependOn(&check.step);
838
839 return test_step;
840}
841
842fn testIFuncAlias(b: *Build, opts: Options) *Step {
843 const test_step = addTestStep(b, "ifunc-alias", opts);
844
845 const exe = addExecutable(b, "main", opts);
846 addCSourceBytes(exe,
847 \\#include <assert.h>
848 \\void foo() {}
849 \\int bar() __attribute__((ifunc("resolve_bar")));
850 \\void *resolve_bar() { return foo; }
851 \\void *bar2 = bar;
852 \\int main() {
853 \\ assert(bar == bar2);
854 \\}
855 , &.{});
856 exe.force_pic = true;
857 exe.linkLibC();
858
859 const run = addRunArtifact(exe);
860 run.expectExitCode(0);
861 test_step.dependOn(&run.step);
862
863 return test_step;
864}
865
866fn testIFuncDlopen(b: *Build, opts: Options) *Step {
867 const test_step = addTestStep(b, "ifunc-dlopen", opts);
868
869 const dso = addSharedLibrary(b, "a", opts);
870 addCSourceBytes(dso,
871 \\__attribute__((ifunc("resolve_foo")))
872 \\void foo(void);
873 \\static void real_foo(void) {
874 \\}
875 \\typedef void Func();
876 \\static Func *resolve_foo(void) {
877 \\ return real_foo;
878 \\}
879 , &.{});
880
881 const exe = addExecutable(b, "main", opts);
882 addCSourceBytes(exe,
883 \\#include <dlfcn.h>
884 \\#include <assert.h>
885 \\#include <stdlib.h>
886 \\typedef void Func();
887 \\void foo(void);
888 \\int main() {
889 \\ void *handle = dlopen(NULL, RTLD_NOW);
890 \\ Func *p = dlsym(handle, "foo");
891 \\
892 \\ foo();
893 \\ p();
894 \\ assert(foo == p);
895 \\}
896 , &.{});
897 exe.linkLibrary(dso);
898 exe.linkLibC();
899 exe.linkSystemLibrary2("dl", .{});
900 exe.force_pic = false;
901 exe.pie = false;
902
903 const run = addRunArtifact(exe);
904 test_step.dependOn(&run.step);
905
906 return test_step;
907}
908
909fn testIFuncDso(b: *Build, opts: Options) *Step {
910 const test_step = addTestStep(b, "ifunc-dso", opts);
911
912 const dso = addSharedLibrary(b, "a", opts);
913 addCSourceBytes(dso,
914 \\#include<stdio.h>
915 \\__attribute__((ifunc("resolve_foobar")))
916 \\void foobar(void);
917 \\static void real_foobar(void) {
918 \\ printf("Hello world\n");
919 \\}
920 \\typedef void Func();
921 \\static Func *resolve_foobar(void) {
922 \\ return real_foobar;
923 \\}
924 , &.{});
925 dso.linkLibC();
926
927 const exe = addExecutable(b, "main", opts);
928 addCSourceBytes(exe,
929 \\void foobar(void);
930 \\int main() {
931 \\ foobar();
932 \\}
933 , &.{});
934 exe.linkLibrary(dso);
935
936 const run = addRunArtifact(exe);
937 run.expectStdOutEqual("Hello world\n");
938 test_step.dependOn(&run.step);
939
940 return test_step;
941}
942
943fn testIFuncDynamic(b: *Build, opts: Options) *Step {
944 const test_step = addTestStep(b, "ifunc-dynamic", opts);
945
946 const main_c =
947 \\#include <stdio.h>
948 \\__attribute__((ifunc("resolve_foobar")))
949 \\static void foobar(void);
950 \\static void real_foobar(void) {
951 \\ printf("Hello world\n");
952 \\}
953 \\typedef void Func();
954 \\static Func *resolve_foobar(void) {
955 \\ return real_foobar;
956 \\}
957 \\int main() {
958 \\ foobar();
959 \\}
960 ;
961
962 {
963 const exe = addExecutable(b, "main", opts);
964 addCSourceBytes(exe, main_c, &.{});
965 exe.linkLibC();
966 exe.link_z_lazy = true;
967
968 const run = addRunArtifact(exe);
969 run.expectStdOutEqual("Hello world\n");
970 test_step.dependOn(&run.step);
971 }
972 {
973 const exe = addExecutable(b, "other", opts);
974 addCSourceBytes(exe, main_c, &.{});
975 exe.linkLibC();
976
977 const run = addRunArtifact(exe);
978 run.expectStdOutEqual("Hello world\n");
979 test_step.dependOn(&run.step);
980 }
981
982 return test_step;
983}
984
985fn testIFuncExport(b: *Build, opts: Options) *Step {
986 const test_step = addTestStep(b, "ifunc-export", opts);
987
988 const dso = addSharedLibrary(b, "a", opts);
989 addCSourceBytes(dso,
990 \\#include <stdio.h>
991 \\__attribute__((ifunc("resolve_foobar")))
992 \\void foobar(void);
993 \\void real_foobar(void) {
994 \\ printf("Hello world\n");
995 \\}
996 \\typedef void Func();
997 \\Func *resolve_foobar(void) {
998 \\ return real_foobar;
999 \\}
1000 , &.{});
1001 dso.linkLibC();
1002
1003 const check = dso.checkObject();
1004 check.checkInDynamicSymtab();
1005 check.checkContains("IFUNC GLOBAL DEFAULT foobar");
1006 test_step.dependOn(&check.step);
1007
1008 return test_step;
1009}
1010
1011fn testIFuncFuncPtr(b: *Build, opts: Options) *Step {
1012 const test_step = addTestStep(b, "ifunc-func-ptr", opts);
1013
1014 const exe = addExecutable(b, "main", opts);
1015 addCSourceBytes(exe,
1016 \\typedef int Fn();
1017 \\int foo() __attribute__((ifunc("resolve_foo")));
1018 \\int real_foo() { return 3; }
1019 \\Fn *resolve_foo(void) {
1020 \\ return real_foo;
1021 \\}
1022 , &.{});
1023 addCSourceBytes(exe,
1024 \\typedef int Fn();
1025 \\int foo();
1026 \\Fn *get_foo() { return foo; }
1027 , &.{});
1028 addCSourceBytes(exe,
1029 \\#include <stdio.h>
1030 \\typedef int Fn();
1031 \\Fn *get_foo();
1032 \\int main() {
1033 \\ Fn *f = get_foo();
1034 \\ printf("%d\n", f());
1035 \\}
1036 , &.{});
1037 exe.force_pic = true;
1038 exe.linkLibC();
1039
1040 const run = addRunArtifact(exe);
1041 run.expectStdOutEqual("3\n");
1042 test_step.dependOn(&run.step);
1043
1044 return test_step;
1045}
1046
1047fn testIFuncNoPlt(b: *Build, opts: Options) *Step {
1048 const test_step = addTestStep(b, "ifunc-noplt", opts);
1049
1050 const exe = addExecutable(b, "main", opts);
1051 addCSourceBytes(exe,
1052 \\#include <stdio.h>
1053 \\__attribute__((ifunc("resolve_foo")))
1054 \\void foo(void);
1055 \\void hello(void) {
1056 \\ printf("Hello world\n");
1057 \\}
1058 \\typedef void Fn();
1059 \\Fn *resolve_foo(void) {
1060 \\ return hello;
1061 \\}
1062 \\int main() {
1063 \\ foo();
1064 \\}
1065 , &.{"-fno-plt"});
1066 exe.force_pic = true;
1067 exe.linkLibC();
1068
1069 const run = addRunArtifact(exe);
1070 run.expectStdOutEqual("Hello world\n");
1071 test_step.dependOn(&run.step);
1072
1073 return test_step;
1074}
1075
1076fn testIFuncStatic(b: *Build, opts: Options) *Step {
1077 const test_step = addTestStep(b, "ifunc-static", opts);
1078
1079 const exe = addExecutable(b, "main", opts);
1080 addCSourceBytes(exe,
1081 \\#include <stdio.h>
1082 \\void foo() __attribute__((ifunc("resolve_foo")));
1083 \\void hello() {
1084 \\ printf("Hello world\n");
1085 \\}
1086 \\void *resolve_foo() {
1087 \\ return hello;
1088 \\}
1089 \\int main() {
1090 \\ foo();
1091 \\ return 0;
1092 \\}
1093 , &.{});
1094 exe.linkLibC();
1095 exe.linkage = .static;
1096
1097 const run = addRunArtifact(exe);
1098 run.expectStdOutEqual("Hello world\n");
1099 test_step.dependOn(&run.step);
1100
1101 return test_step;
1102}
1103
1104fn testIFuncStaticPie(b: *Build, opts: Options) *Step {
1105 const test_step = addTestStep(b, "ifunc-static-pie", opts);
1106
1107 const exe = addExecutable(b, "main", opts);
1108 addCSourceBytes(exe,
1109 \\#include <stdio.h>
1110 \\void foo() __attribute__((ifunc("resolve_foo")));
1111 \\void hello() {
1112 \\ printf("Hello world\n");
1113 \\}
1114 \\void *resolve_foo() {
1115 \\ return hello;
1116 \\}
1117 \\int main() {
1118 \\ foo();
1119 \\ return 0;
1120 \\}
1121 , &.{});
1122 exe.linkage = .static;
1123 exe.force_pic = true;
1124 exe.pie = true;
1125 exe.linkLibC();
1126
1127 const run = addRunArtifact(exe);
1128 run.expectStdOutEqual("Hello world\n");
1129 test_step.dependOn(&run.step);
1130
1131 const check = exe.checkObject();
1132 check.checkStart();
1133 check.checkExact("header");
1134 check.checkExact("type DYN");
1135 check.checkStart();
1136 check.checkExact("section headers");
1137 check.checkExact("name .dynamic");
1138 check.checkStart();
1139 check.checkExact("section headers");
1140 check.checkNotPresent("name .interp");
1141 test_step.dependOn(&check.step);
1142
1143 return test_step;
1144}
1145
1146fn testImageBase(b: *Build, opts: Options) *Step {
1147 const test_step = addTestStep(b, "image-base", opts);
1148
1149 {
1150 const exe = addExecutable(b, "main1", opts);
1151 addCSourceBytes(exe,
1152 \\#include <stdio.h>
1153 \\int main() {
1154 \\ printf("Hello World!\n");
1155 \\ return 0;
1156 \\}
1157 , &.{});
1158 exe.linkLibC();
1159 exe.image_base = 0x8000000;
1160
1161 const run = addRunArtifact(exe);
1162 run.expectStdOutEqual("Hello World!\n");
1163 test_step.dependOn(&run.step);
1164
1165 const check = exe.checkObject();
1166 check.checkStart();
1167 check.checkExact("header");
1168 check.checkExtract("entry {addr}");
1169 check.checkComputeCompare("addr", .{ .op = .gte, .value = .{ .literal = 0x8000000 } });
1170 test_step.dependOn(&check.step);
1171 }
1172
1173 {
1174 const exe = addExecutable(b, "main2", opts);
1175 addCSourceBytes(exe, "void _start() {}", &.{});
1176 exe.image_base = 0xffffffff8000000;
1177
1178 const check = exe.checkObject();
1179 check.checkStart();
1180 check.checkExact("header");
1181 check.checkExtract("entry {addr}");
1182 check.checkComputeCompare("addr", .{ .op = .gte, .value = .{ .literal = 0xffffffff8000000 } });
1183 test_step.dependOn(&check.step);
1184 }
1185
1186 return test_step;
1187}
1188
1189fn testInitArrayOrder(b: *Build, opts: Options) *Step {
1190 const test_step = addTestStep(b, "init-array-order", opts);
1191
1192 const a_o = addObject(b, "a", opts);
1193 addCSourceBytes(a_o,
1194 \\#include <stdio.h>
1195 \\__attribute__((constructor(10000))) void init4() { printf("1"); }
1196 , &.{});
1197 a_o.linkLibC();
1198
1199 const b_o = addObject(b, "b", opts);
1200 addCSourceBytes(b_o,
1201 \\#include <stdio.h>
1202 \\__attribute__((constructor(1000))) void init3() { printf("2"); }
1203 , &.{});
1204 b_o.linkLibC();
1205
1206 const c_o = addObject(b, "c", opts);
1207 addCSourceBytes(c_o,
1208 \\#include <stdio.h>
1209 \\__attribute__((constructor)) void init1() { printf("3"); }
1210 , &.{});
1211 c_o.linkLibC();
1212
1213 const d_o = addObject(b, "d", opts);
1214 addCSourceBytes(d_o,
1215 \\#include <stdio.h>
1216 \\__attribute__((constructor)) void init2() { printf("4"); }
1217 , &.{});
1218 d_o.linkLibC();
1219
1220 const e_o = addObject(b, "e", opts);
1221 addCSourceBytes(e_o,
1222 \\#include <stdio.h>
1223 \\__attribute__((destructor(10000))) void fini4() { printf("5"); }
1224 , &.{});
1225 e_o.linkLibC();
1226
1227 const f_o = addObject(b, "f", opts);
1228 addCSourceBytes(f_o,
1229 \\#include <stdio.h>
1230 \\__attribute__((destructor(1000))) void fini3() { printf("6"); }
1231 , &.{});
1232 f_o.linkLibC();
1233
1234 const g_o = addObject(b, "g", opts);
1235 addCSourceBytes(g_o,
1236 \\#include <stdio.h>
1237 \\__attribute__((destructor)) void fini1() { printf("7"); }
1238 , &.{});
1239 g_o.linkLibC();
1240
1241 const h_o = addObject(b, "h", opts);
1242 addCSourceBytes(h_o,
1243 \\#include <stdio.h>
1244 \\__attribute__((destructor)) void fini2() { printf("8"); }
1245 , &.{});
1246 h_o.linkLibC();
1247
1248 const exe = addExecutable(b, "main", opts);
1249 addCSourceBytes(exe, "int main() { return 0; }", &.{});
1250 exe.addObject(a_o);
1251 exe.addObject(b_o);
1252 exe.addObject(c_o);
1253 exe.addObject(d_o);
1254 exe.addObject(e_o);
1255 exe.addObject(f_o);
1256 exe.addObject(g_o);
1257 exe.addObject(h_o);
1258
1259 const run = addRunArtifact(exe);
1260 run.expectStdOutEqual("21348756");
1261 test_step.dependOn(&run.step);
1262
1263 return test_step;
1264}
1265
7791266fn testLargeAlignmentDso(b: *Build, opts: Options) *Step {
7801267 const test_step = addTestStep(b, "large-alignment-dso", opts);
7811268
......@@ -951,6 +1438,37 @@ fn testLinkingZig(b: *Build, opts: Options) *Step {
9511438 return test_step;
9521439}
9531440
1441fn testPie(b: *Build, opts: Options) *Step {
1442 const test_step = addTestStep(b, "hello-pie", opts);
1443
1444 const exe = addExecutable(b, "main", opts);
1445 addCSourceBytes(exe,
1446 \\#include <stdio.h>
1447 \\int main() {
1448 \\ printf("Hello!\n");
1449 \\ return 0;
1450 \\}
1451 , &.{});
1452 exe.linkLibC();
1453 exe.force_pic = true;
1454 exe.pie = true;
1455
1456 const run = addRunArtifact(exe);
1457 run.expectStdOutEqual("Hello!\n");
1458 test_step.dependOn(&run.step);
1459
1460 const check = exe.checkObject();
1461 check.checkStart();
1462 check.checkExact("header");
1463 check.checkExact("type DYN");
1464 check.checkStart();
1465 check.checkExact("section headers");
1466 check.checkExact("name .dynamic");
1467 test_step.dependOn(&check.step);
1468
1469 return test_step;
1470}
1471
9541472fn testTlsStatic(b: *Build, opts: Options) *Step {
9551473 const test_step = addTestStep(b, "tls-static", opts);
9561474