@@ -6,9 +6,12 @@ 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;
13+ use std:: error:: Error ;
14+ use std:: fmt;
1215use std:: fs;
1316use std:: fs:: create_dir_all;
1417use std:: io:: { BufRead , BufReader , Cursor , Error as IOError , Read , Write } ;
@@ -1126,7 +1129,13 @@ fn make_config_c(
11261129 }
11271130
11281131 for em in built_extension_modules. values ( ) {
1129- lines. push ( format ! ( "extern PyObject* {}(void);" , em. init_fn) ) ;
1132+ let name_prefix = em. name . split ( '.' ) . next ( ) . unwrap ( ) ;
1133+ if em. init_fn . contains ( name_prefix) {
1134+ lines. push ( format ! ( "extern PyObject* {}(void);" , em. init_fn) ) ;
1135+ }
1136+ else {
1137+ lines. push ( format ! ( "extern PyObject* PyInit_{}(void);" , em. name. replace( "." , "_" ) ) ) ;
1138+ }
11301139 }
11311140
11321141 lines. push ( String :: from ( "struct _inittab _PyImport_Inittab[] = {" ) ) ;
@@ -1142,7 +1151,13 @@ fn make_config_c(
11421151 }
11431152
11441153 for em in built_extension_modules. values ( ) {
1145- lines. push ( format ! ( "{{\" {}\" , {}}}," , em. name, em. init_fn) ) ;
1154+ let name_prefix = em. name . split ( '.' ) . next ( ) . unwrap ( ) ;
1155+ if em. init_fn . contains ( name_prefix) {
1156+ lines. push ( format ! ( "{{\" {}\" , {}}}," , em. name, em. init_fn) ) ;
1157+ }
1158+ else {
1159+ lines. push ( format ! ( "{{\" {}\" , PyInit_{}}}," , em. name, em. name. replace( "." , "_" ) ) ) ;
1160+ }
11461161 }
11471162
11481163 lines. push ( String :: from ( "{0, 0}" ) ) ;
@@ -1151,6 +1166,142 @@ fn make_config_c(
11511166 lines. join ( "\n " )
11521167}
11531168
1169+ #[ derive( Debug , Clone ) ]
1170+ struct NoRewriteError ;
1171+
1172+ impl fmt:: Display for NoRewriteError {
1173+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1174+ write ! ( f, "no object rewriting was performed" )
1175+ }
1176+ }
1177+
1178+ impl Error for NoRewriteError {
1179+ fn source ( & self ) -> Option < & ( dyn Error + ' static ) > {
1180+ // Generic error, underlying cause isn't tracked.
1181+ None
1182+ }
1183+ }
1184+
1185+ /// Rename object syn PyInit_foo to PyInit_<full_name> to avoid clashes
1186+ fn rename_init (
1187+ logger : & slog:: Logger ,
1188+ name : & String ,
1189+ object_data : & [ u8 ]
1190+ ) -> Result < Vec < u8 > , NoRewriteError > {
1191+ let mut rewritten = false ;
1192+
1193+ let name_prefix = name. split ( '.' ) . next ( ) . unwrap ( ) ;
1194+
1195+ let in_object = match object:: File :: parse ( object_data) {
1196+ Ok ( object) => object,
1197+ Err ( err) => {
1198+ panic ! ( "Failed to parse compiled object for {}: {}" , name, err) ;
1199+ }
1200+ } ;
1201+
1202+ let mut out_object = write:: Object :: new ( in_object. format ( ) , in_object. architecture ( ) ) ;
1203+ out_object. mangling = write:: Mangling :: None ;
1204+
1205+ let mut out_sections = HashMap :: new ( ) ;
1206+ for in_section in in_object. sections ( ) {
1207+ if in_section. kind ( ) == SectionKind :: Metadata {
1208+ continue ;
1209+ }
1210+ let section_id = out_object. add_section (
1211+ in_section. segment_name ( ) . unwrap_or ( "" ) . as_bytes ( ) . to_vec ( ) ,
1212+ in_section. name ( ) . unwrap_or ( "" ) . as_bytes ( ) . to_vec ( ) ,
1213+ in_section. kind ( ) ,
1214+ ) ;
1215+ let out_section = out_object. section_mut ( section_id) ;
1216+ if out_section. is_bss ( ) {
1217+ out_section. append_bss ( in_section. size ( ) , in_section. align ( ) ) ;
1218+ } else {
1219+ out_section. set_data ( in_section. uncompressed_data ( ) . into ( ) , in_section. align ( ) ) ;
1220+ }
1221+ out_sections. insert ( in_section. index ( ) , section_id) ;
1222+ }
1223+
1224+ let mut out_symbols = HashMap :: new ( ) ;
1225+ for ( symbol_index, in_symbol) in in_object. symbols ( ) {
1226+ if in_symbol. kind ( ) == SymbolKind :: Null {
1227+ continue ;
1228+ }
1229+ let ( section, value) = match in_symbol. section_index ( ) {
1230+ Some ( index) => (
1231+ Some ( * out_sections. get ( & index) . unwrap ( ) ) ,
1232+ in_symbol. address ( ) - in_object. section_by_index ( index) . unwrap ( ) . address ( ) ,
1233+ ) ,
1234+ None => ( None , in_symbol. address ( ) ) ,
1235+ } ;
1236+ let in_sym_name = in_symbol. name ( ) . unwrap_or ( "" ) ;
1237+ let sym_name = if in_sym_name. starts_with ( "PyInit_" ) && !in_sym_name. contains ( name_prefix) {
1238+ format ! ( "PyInit_{}" , name. replace( "." , "_" ) )
1239+ } else {
1240+ String :: from ( in_sym_name)
1241+ } ;
1242+ if sym_name != in_sym_name {
1243+ warn ! (
1244+ logger,
1245+ "rewrote object symbol name {} to {}" ,
1246+ in_sym_name,
1247+ sym_name,
1248+ ) ;
1249+
1250+ rewritten = true ;
1251+ }
1252+
1253+ let out_symbol = write:: Symbol {
1254+ name : sym_name. as_bytes ( ) . to_vec ( ) ,
1255+ value,
1256+ size : in_symbol. size ( ) ,
1257+ kind : in_symbol. kind ( ) ,
1258+ scope : in_symbol. scope ( ) ,
1259+ weak : in_symbol. is_weak ( ) ,
1260+ section,
1261+ } ;
1262+ let symbol_id = out_object. add_symbol ( out_symbol) ;
1263+ out_symbols. insert ( symbol_index, symbol_id) ;
1264+ }
1265+
1266+
1267+ if !rewritten {
1268+ info ! (
1269+ logger,
1270+ "no symbol name rewriting occurred for {}" ,
1271+ name,
1272+ ) ;
1273+ return Err ( NoRewriteError )
1274+ }
1275+
1276+ for in_section in in_object. sections ( ) {
1277+ if in_section. kind ( ) == SectionKind :: Metadata {
1278+ continue ;
1279+ }
1280+ let out_section = * out_sections. get ( & in_section. index ( ) ) . unwrap ( ) ;
1281+ for ( offset, in_relocation) in in_section. relocations ( ) {
1282+ let symbol = match in_relocation. target ( ) {
1283+ RelocationTarget :: Symbol ( symbol) => * out_symbols. get ( & symbol) . unwrap ( ) ,
1284+ RelocationTarget :: Section ( section) => {
1285+ out_object. section_symbol ( * out_sections. get ( & section) . unwrap ( ) )
1286+ }
1287+ } ;
1288+ let out_relocation = write:: Relocation {
1289+ offset,
1290+ size : in_relocation. size ( ) ,
1291+ kind : in_relocation. kind ( ) ,
1292+ encoding : in_relocation. encoding ( ) ,
1293+ symbol,
1294+ addend : in_relocation. addend ( ) ,
1295+ } ;
1296+ out_object
1297+ . add_relocation ( out_section, out_relocation)
1298+ . unwrap ( ) ;
1299+ }
1300+ }
1301+
1302+ Ok ( out_object. write ( ) . unwrap ( ) )
1303+ }
1304+
11541305#[ derive( Debug ) ]
11551306pub struct LibpythonInfo {
11561307 path : PathBuf ,
@@ -1341,7 +1492,11 @@ pub fn link_libpython(
13411492 for ( i, object_data) in em. object_file_data . iter ( ) . enumerate ( ) {
13421493 let out_path = temp_dir_path. join ( format ! ( "{}.{}.o" , name, i) ) ;
13431494
1344- fs:: write ( & out_path, object_data) . expect ( "unable to write object file" ) ;
1495+ match rename_init ( logger, name, object_data) {
1496+ Ok ( val) => fs:: write ( & out_path, val) . expect ( "unable to write object file" ) ,
1497+ Err ( _) => fs:: write ( & out_path, object_data) . expect ( "unable to write object file" )
1498+ } ;
1499+
13451500 build. object ( & out_path) ;
13461501 }
13471502
0 commit comments