@@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
4
4
5
5
use rustc_abi:: Endian ;
6
6
use rustc_data_structures:: base_n:: { CASE_INSENSITIVE , ToBaseN } ;
7
- use rustc_data_structures:: fx:: FxIndexMap ;
7
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
8
8
use rustc_data_structures:: stable_hasher:: StableHasher ;
9
9
use rustc_hashes:: Hash128 ;
10
10
use rustc_session:: Session ;
@@ -230,40 +230,66 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
230
230
Endian :: Little => object:: Endianness :: Little ,
231
231
Endian :: Big => object:: Endianness :: Big ,
232
232
} ;
233
+
233
234
let mut stub = write:: Writer :: new ( endianness, true , & mut stub_buf) ;
234
235
236
+ let mut vers = Vec :: new ( ) ;
237
+ let mut vers_map = FxHashMap :: default ( ) ;
238
+ let mut syms = Vec :: new ( ) ;
239
+
240
+ for symbol in symbols {
241
+ let symbol_name = symbol. name . as_str ( ) ;
242
+ if let Some ( ( name, version_name) ) = symbol_name. split_once ( '@' ) {
243
+ assert ! ( !version_name. contains( '@' ) ) ;
244
+ let dynstr = stub. add_dynamic_string ( name. as_bytes ( ) ) ;
245
+ let ver = if let Some ( & ver_id) = vers_map. get ( version_name) {
246
+ ver_id
247
+ } else {
248
+ let id = vers. len ( ) ;
249
+ vers_map. insert ( version_name, id) ;
250
+ let dynstr = stub. add_dynamic_string ( version_name. as_bytes ( ) ) ;
251
+ vers. push ( ( version_name, dynstr) ) ;
252
+ id
253
+ } ;
254
+ syms. push ( ( name, dynstr, Some ( ver) ) ) ;
255
+ } else {
256
+ let dynstr = stub. add_dynamic_string ( symbol_name. as_bytes ( ) ) ;
257
+ syms. push ( ( symbol_name, dynstr, None ) ) ;
258
+ }
259
+ }
260
+
261
+ let soname = stub. add_dynamic_string ( soname. as_bytes ( ) ) ;
262
+
235
263
// These initial reservations don't reserve any bytes in the binary yet,
236
264
// they just allocate in the internal data structures.
237
265
238
266
// First, we crate the dynamic symbol table. It starts with a null symbol
239
267
// and then all the symbols and their dynamic strings.
240
268
stub. reserve_null_dynamic_symbol_index ( ) ;
241
269
242
- let dynstrs = symbols
243
- . iter ( )
244
- . map ( |sym| {
245
- stub. reserve_dynamic_symbol_index ( ) ;
246
- ( sym, stub. add_dynamic_string ( sym. name . as_str ( ) . as_bytes ( ) ) )
247
- } )
248
- . collect :: < Vec < _ > > ( ) ;
249
-
250
- let soname = stub. add_dynamic_string ( soname. as_bytes ( ) ) ;
270
+ for _ in syms. iter ( ) {
271
+ stub. reserve_dynamic_symbol_index ( ) ;
272
+ }
251
273
252
274
// Reserve the sections.
253
275
// We have the minimal sections for a dynamic SO and .text where we point our dummy symbols to.
254
276
stub. reserve_shstrtab_section_index ( ) ;
255
277
let text_section_name = stub. add_section_name ( ".text" . as_bytes ( ) ) ;
256
278
let text_section = stub. reserve_section_index ( ) ;
257
- stub. reserve_dynstr_section_index ( ) ;
258
279
stub. reserve_dynsym_section_index ( ) ;
280
+ stub. reserve_dynstr_section_index ( ) ;
281
+ stub. reserve_gnu_versym_section_index ( ) ;
282
+ stub. reserve_gnu_verdef_section_index ( ) ;
259
283
stub. reserve_dynamic_section_index ( ) ;
260
284
261
285
// These reservations now determine the actual layout order of the object file.
262
286
stub. reserve_file_header ( ) ;
263
287
stub. reserve_shstrtab ( ) ;
264
288
stub. reserve_section_headers ( ) ;
265
- stub. reserve_dynstr ( ) ;
266
289
stub. reserve_dynsym ( ) ;
290
+ stub. reserve_dynstr ( ) ;
291
+ stub. reserve_gnu_versym ( ) ;
292
+ stub. reserve_gnu_verdef ( 1 + vers. len ( ) , 1 + vers. len ( ) ) ;
267
293
stub. reserve_dynamic ( 2 ) ; // DT_SONAME, DT_NULL
268
294
269
295
// First write the ELF header with the arch information.
@@ -342,18 +368,17 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
342
368
sh_addralign : 1 ,
343
369
sh_entsize : 0 ,
344
370
} ) ;
345
- stub. write_dynstr_section_header ( 0 ) ;
346
371
stub. write_dynsym_section_header ( 0 , 1 ) ;
372
+ stub. write_dynstr_section_header ( 0 ) ;
373
+ stub. write_gnu_versym_section_header ( 0 ) ;
374
+ stub. write_gnu_verdef_section_header ( 0 ) ;
347
375
stub. write_dynamic_section_header ( 0 ) ;
348
376
349
- // .dynstr
350
- stub. write_dynstr ( ) ;
351
-
352
377
// .dynsym
353
378
stub. write_null_dynamic_symbol ( ) ;
354
- for ( _ , name ) in dynstrs {
379
+ for ( _name , dynstr , _ver ) in syms . iter ( ) . copied ( ) {
355
380
stub. write_dynamic_symbol ( & write:: Sym {
356
- name : Some ( name ) ,
381
+ name : Some ( dynstr ) ,
357
382
st_info : ( elf:: STB_GLOBAL << 4 ) | elf:: STT_NOTYPE ,
358
383
st_other : elf:: STV_DEFAULT ,
359
384
section : Some ( text_section) ,
@@ -363,10 +388,44 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
363
388
} ) ;
364
389
}
365
390
391
+ // .dynstr
392
+ stub. write_dynstr ( ) ;
393
+
394
+ // .gnu_version
395
+ stub. write_null_gnu_versym ( ) ;
396
+ for ( _name, _dynstr, ver) in syms. iter ( ) . copied ( ) {
397
+ stub. write_gnu_versym ( if let Some ( ver) = ver {
398
+ assert ! ( ( 2 + ver as u16 ) < elf:: VERSYM_HIDDEN ) ;
399
+ elf:: VERSYM_HIDDEN | ( 2 + ver as u16 )
400
+ } else {
401
+ 1
402
+ } ) ;
403
+ }
404
+
405
+ // .gnu_version_d
406
+ stub. write_align_gnu_verdef ( ) ;
407
+ stub. write_gnu_verdef ( & write:: Verdef {
408
+ version : elf:: VER_DEF_CURRENT ,
409
+ flags : elf:: VER_FLG_BASE ,
410
+ index : 1 ,
411
+ aux_count : 1 ,
412
+ name : soname,
413
+ } ) ;
414
+ for ( ver, ( _name, dynstr) ) in vers. into_iter ( ) . enumerate ( ) {
415
+ stub. write_gnu_verdef ( & write:: Verdef {
416
+ version : elf:: VER_DEF_CURRENT ,
417
+ flags : 0 ,
418
+ index : 2 + ver as u16 ,
419
+ aux_count : 1 ,
420
+ name : dynstr,
421
+ } ) ;
422
+ }
423
+
366
424
// .dynamic
367
425
// the DT_SONAME will be used by the linker to populate DT_NEEDED
368
426
// which the loader uses to find the library.
369
427
// DT_NULL terminates the .dynamic table.
428
+ stub. write_align_dynamic ( ) ;
370
429
stub. write_dynamic_string ( elf:: DT_SONAME , soname) ;
371
430
stub. write_dynamic ( elf:: DT_NULL , 0 ) ;
372
431
0 commit comments