@@ -849,6 +849,23 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
849849 var opt_symbol_name : ? []const u8 = null ;
850850 var versions_buffer : [32 ]u8 = undefined ;
851851 var versions_len : usize = undefined ;
852+
853+ // There can be situations where there are multiple inclusions for the same symbol with
854+ // overlapping versions. For example:
855+ //
856+ // lgammal:
857+ // library: libm.so
858+ // versions: 2.4 2.23
859+ // targets: ... s390x-linux-gnu ...
860+ // lgammal:
861+ // library: libm.so
862+ // versions: 2.2 2.23
863+ // targets: ... s390x-linux-gnu ...
864+ //
865+ // If we don't handle this, we end up writing the default `lgammal` symbol for version 2.33
866+ // twice, which causes a "duplicate symbol" assembler error.
867+ var versions_written = std .AutoArrayHashMap (Version , void ).init (arena );
868+
852869 while (sym_i < fn_inclusions_len ) : (sym_i += 1 ) {
853870 const sym_name = opt_symbol_name orelse n : {
854871 const name = mem .sliceTo (metadata .inclusions [inc_i .. ], 0 );
@@ -902,6 +919,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
902919 }
903920 }
904921 }
922+
923+ versions_written .clearRetainingCapacity ();
924+ try versions_written .ensureTotalCapacity (versions_len );
925+
905926 {
906927 var ver_buf_i : u8 = 0 ;
907928 while (ver_buf_i < versions_len ) : (ver_buf_i += 1 ) {
@@ -912,6 +933,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
912933 // _Exit_2_2_5:
913934 const ver_index = versions_buffer [ver_buf_i ];
914935 const ver = metadata .all_versions [ver_index ];
936+
937+ if (versions_written .getOrPutAssumeCapacity (ver ).found_existing ) continue ;
938+
915939 // Default symbol version definition vs normal symbol version definition
916940 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index ;
917941 const at_sign_str : []const u8 = if (want_default ) "@@" else "@" ;
@@ -1061,6 +1085,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
10611085 }
10621086 }
10631087 }
1088+
1089+ versions_written .clearRetainingCapacity ();
1090+ try versions_written .ensureTotalCapacity (versions_len );
1091+
10641092 {
10651093 var ver_buf_i : u8 = 0 ;
10661094 while (ver_buf_i < versions_len ) : (ver_buf_i += 1 ) {
@@ -1072,6 +1100,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
10721100 // environ_2_2_5:
10731101 const ver_index = versions_buffer [ver_buf_i ];
10741102 const ver = metadata .all_versions [ver_index ];
1103+
1104+ if (versions_written .getOrPutAssumeCapacity (ver ).found_existing ) continue ;
1105+
10751106 // Default symbol version definition vs normal symbol version definition
10761107 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index ;
10771108 const at_sign_str : []const u8 = if (want_default ) "@@" else "@" ;
0 commit comments