@@ -6,8 +6,9 @@ use byteorder::{LittleEndian, WriteBytesExt};
66use glob:: glob as findglob;
77use itertools:: Itertools ;
88use lazy_static:: lazy_static;
9+ use object:: { write, Object , ObjectSection , RelocationTarget , SectionKind , SymbolKind } ;
910use slog:: { info, warn} ;
10- use std:: collections:: { BTreeMap , BTreeSet } ;
11+ use std:: collections:: { BTreeMap , BTreeSet , HashMap } ;
1112use std:: env;
1213use std:: fs;
1314use std:: fs:: create_dir_all;
@@ -1126,7 +1127,7 @@ fn make_config_c(
11261127 }
11271128
11281129 for em in built_extension_modules. values ( ) {
1129- lines. push ( format ! ( "extern PyObject* {}(void);" , em. init_fn ) ) ;
1130+ lines. push ( format ! ( "extern PyObject* PyInit_ {}(void);" , em. name . replace ( "." , "_" ) ) ) ;
11301131 }
11311132
11321133 lines. push ( String :: from ( "struct _inittab _PyImport_Inittab[] = {" ) ) ;
@@ -1142,7 +1143,7 @@ fn make_config_c(
11421143 }
11431144
11441145 for em in built_extension_modules. values ( ) {
1145- lines. push ( format ! ( "{{\" {}\" , {}}}," , em. name, em. init_fn ) ) ;
1146+ lines. push ( format ! ( "{{\" {}\" , PyInit_ {}}}," , em. name, em. name . replace ( "." , "_" ) ) ) ;
11461147 }
11471148
11481149 lines. push ( String :: from ( "{0, 0}" ) ) ;
@@ -1151,6 +1152,101 @@ fn make_config_c(
11511152 lines. join ( "\n " )
11521153}
11531154
1155+ /// Rename object syn PyInit_foo to PyInit_<full_name> to avoid clashes
1156+ fn rename_init (
1157+ name : & String ,
1158+ object_data : & [ u8 ]
1159+ ) -> Vec < u8 > {
1160+ let in_object = match object:: File :: parse ( object_data) {
1161+ Ok ( object) => object,
1162+ Err ( err) => {
1163+ panic ! ( "Failed to parse compiled object for {}: {}" , name, err) ;
1164+ }
1165+ } ;
1166+
1167+ let mut out_object = write:: Object :: new ( in_object. format ( ) , in_object. architecture ( ) ) ;
1168+ out_object. mangling = write:: Mangling :: None ;
1169+
1170+ let mut out_sections = HashMap :: new ( ) ;
1171+ for in_section in in_object. sections ( ) {
1172+ if in_section. kind ( ) == SectionKind :: Metadata {
1173+ continue ;
1174+ }
1175+ let section_id = out_object. add_section (
1176+ in_section. segment_name ( ) . unwrap_or ( "" ) . as_bytes ( ) . to_vec ( ) ,
1177+ in_section. name ( ) . unwrap_or ( "" ) . as_bytes ( ) . to_vec ( ) ,
1178+ in_section. kind ( ) ,
1179+ ) ;
1180+ let out_section = out_object. section_mut ( section_id) ;
1181+ if out_section. is_bss ( ) {
1182+ out_section. append_bss ( in_section. size ( ) , in_section. align ( ) ) ;
1183+ } else {
1184+ out_section. set_data ( in_section. uncompressed_data ( ) . into ( ) , in_section. align ( ) ) ;
1185+ }
1186+ out_sections. insert ( in_section. index ( ) , section_id) ;
1187+ }
1188+
1189+ let mut out_symbols = HashMap :: new ( ) ;
1190+ for ( symbol_index, in_symbol) in in_object. symbols ( ) {
1191+ if in_symbol. kind ( ) == SymbolKind :: Null {
1192+ continue ;
1193+ }
1194+ let ( section, value) = match in_symbol. section_index ( ) {
1195+ Some ( index) => (
1196+ Some ( * out_sections. get ( & index) . unwrap ( ) ) ,
1197+ in_symbol. address ( ) - in_object. section_by_index ( index) . unwrap ( ) . address ( ) ,
1198+ ) ,
1199+ None => ( None , in_symbol. address ( ) ) ,
1200+ } ;
1201+ let in_sym_name = in_symbol. name ( ) . unwrap_or ( "" ) ;
1202+ let sym_name = if in_sym_name. starts_with ( "PyInit_" ) {
1203+ format ! ( "PyInit_{}" , name. replace( "." , "_" ) )
1204+ } else {
1205+ String :: from ( in_sym_name)
1206+ } ;
1207+
1208+ let out_symbol = write:: Symbol {
1209+ name : sym_name. as_bytes ( ) . to_vec ( ) ,
1210+ value,
1211+ size : in_symbol. size ( ) ,
1212+ kind : in_symbol. kind ( ) ,
1213+ scope : in_symbol. scope ( ) ,
1214+ weak : in_symbol. is_weak ( ) ,
1215+ section,
1216+ } ;
1217+ let symbol_id = out_object. add_symbol ( out_symbol) ;
1218+ out_symbols. insert ( symbol_index, symbol_id) ;
1219+ }
1220+
1221+ for in_section in in_object. sections ( ) {
1222+ if in_section. kind ( ) == SectionKind :: Metadata {
1223+ continue ;
1224+ }
1225+ let out_section = * out_sections. get ( & in_section. index ( ) ) . unwrap ( ) ;
1226+ for ( offset, in_relocation) in in_section. relocations ( ) {
1227+ let symbol = match in_relocation. target ( ) {
1228+ RelocationTarget :: Symbol ( symbol) => * out_symbols. get ( & symbol) . unwrap ( ) ,
1229+ RelocationTarget :: Section ( section) => {
1230+ out_object. section_symbol ( * out_sections. get ( & section) . unwrap ( ) )
1231+ }
1232+ } ;
1233+ let out_relocation = write:: Relocation {
1234+ offset,
1235+ size : in_relocation. size ( ) ,
1236+ kind : in_relocation. kind ( ) ,
1237+ encoding : in_relocation. encoding ( ) ,
1238+ symbol,
1239+ addend : in_relocation. addend ( ) ,
1240+ } ;
1241+ out_object
1242+ . add_relocation ( out_section, out_relocation)
1243+ . unwrap ( ) ;
1244+ }
1245+ }
1246+
1247+ out_object. write ( ) . unwrap ( )
1248+ }
1249+
11541250#[ derive( Debug ) ]
11551251pub struct LibpythonInfo {
11561252 path : PathBuf ,
@@ -1341,7 +1437,9 @@ pub fn link_libpython(
13411437 for ( i, object_data) in em. object_file_data . iter ( ) . enumerate ( ) {
13421438 let out_path = temp_dir_path. join ( format ! ( "{}.{}.o" , name, i) ) ;
13431439
1344- fs:: write ( & out_path, object_data) . expect ( "unable to write object file" ) ;
1440+ let out_data = rename_init ( name, object_data) ;
1441+
1442+ fs:: write ( & out_path, out_data) . expect ( "unable to write object file" ) ;
13451443 build. object ( & out_path) ;
13461444 }
13471445
0 commit comments