@@ -854,6 +854,23 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
854
854
var opt_symbol_name : ? []const u8 = null ;
855
855
var versions_buffer : [32 ]u8 = undefined ;
856
856
var versions_len : usize = undefined ;
857
+
858
+ // There can be situations where there are multiple inclusions for the same symbol with
859
+ // partially overlapping versions, due to different target lists. For example:
860
+ //
861
+ // lgammal:
862
+ // library: libm.so
863
+ // versions: 2.4 2.23
864
+ // targets: ... powerpc64-linux-gnu s390x-linux-gnu
865
+ // lgammal:
866
+ // library: libm.so
867
+ // versions: 2.2 2.23
868
+ // targets: sparc64-linux-gnu s390x-linux-gnu
869
+ //
870
+ // If we don't handle this, we end up writing the default `lgammal` symbol for version 2.33
871
+ // twice, which causes a "duplicate symbol" assembler error.
872
+ var versions_written = std .AutoArrayHashMap (Version , void ).init (arena );
873
+
857
874
while (sym_i < fn_inclusions_len ) : (sym_i += 1 ) {
858
875
const sym_name = opt_symbol_name orelse n : {
859
876
const name = mem .sliceTo (metadata .inclusions [inc_i .. ], 0 );
@@ -907,6 +924,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
907
924
}
908
925
}
909
926
}
927
+
928
+ versions_written .clearRetainingCapacity ();
929
+ try versions_written .ensureTotalCapacity (versions_len );
930
+
910
931
{
911
932
var ver_buf_i : u8 = 0 ;
912
933
while (ver_buf_i < versions_len ) : (ver_buf_i += 1 ) {
@@ -917,6 +938,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
917
938
// _Exit_2_2_5:
918
939
const ver_index = versions_buffer [ver_buf_i ];
919
940
const ver = metadata .all_versions [ver_index ];
941
+
942
+ if (versions_written .getOrPutAssumeCapacity (ver ).found_existing ) continue ;
943
+
920
944
// Default symbol version definition vs normal symbol version definition
921
945
const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index ;
922
946
const at_sign_str : []const u8 = if (want_default ) "@@" else "@" ;
@@ -1066,6 +1090,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
1066
1090
}
1067
1091
}
1068
1092
}
1093
+
1094
+ versions_written .clearRetainingCapacity ();
1095
+ try versions_written .ensureTotalCapacity (versions_len );
1096
+
1069
1097
{
1070
1098
var ver_buf_i : u8 = 0 ;
1071
1099
while (ver_buf_i < versions_len ) : (ver_buf_i += 1 ) {
@@ -1077,6 +1105,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
1077
1105
// environ_2_2_5:
1078
1106
const ver_index = versions_buffer [ver_buf_i ];
1079
1107
const ver = metadata .all_versions [ver_index ];
1108
+
1109
+ if (versions_written .getOrPutAssumeCapacity (ver ).found_existing ) continue ;
1110
+
1080
1111
// Default symbol version definition vs normal symbol version definition
1081
1112
const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index ;
1082
1113
const at_sign_str : []const u8 = if (want_default ) "@@" else "@" ;
0 commit comments