Skip to content

Commit 6321c81

Browse files
refactor: Have linker script emit symbol defs directly (#1364)
1 parent 0d8fd90 commit 6321c81

3 files changed

Lines changed: 75 additions & 70 deletions

File tree

libwild/src/elf_writer.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3076,7 +3076,13 @@ fn write_dynamic_symbol_definitions(
30763076
layout,
30773077
sym_def.symbol_id,
30783078
script,
3079-
)?;
3079+
)
3080+
.with_context(|| {
3081+
format!(
3082+
"Failed to write linker script dynsym: {}",
3083+
layout.symbol_debug(sym_def.symbol_id)
3084+
)
3085+
})?;
30803086
}
30813087
FileLayout::Prelude(prelude) => {
30823088
write_prelude_dynsym(
@@ -3115,14 +3121,13 @@ fn write_linker_script_dynsym(
31153121

31163122
let info = &script.internal_symbols.symbol_definitions[local_index];
31173123

3118-
debug_assert!(
3119-
!matches!(
3120-
info.placement,
3121-
crate::parsing::SymbolPlacement::DefsymSymbol(_)
3122-
| crate::parsing::SymbolPlacement::DefsymAbsolute(_)
3123-
),
3124-
"Defsym symbols from linker scripts should be emitted via the prelude"
3125-
);
3124+
if matches!(
3125+
info.placement,
3126+
crate::parsing::SymbolPlacement::DefsymSymbol(_)
3127+
| crate::parsing::SymbolPlacement::DefsymAbsolute(_)
3128+
) {
3129+
return write_defsym_dynsym(dynsym_writer, layout, symbol_id, info);
3130+
}
31263131

31273132
let section_id = info
31283133
.section_id()

libwild/src/layout.rs

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -328,38 +328,69 @@ fn update_defsym_symbol_resolutions(
328328
symbol_db: &SymbolDb,
329329
resolutions: &mut [Option<Resolution>],
330330
) -> Result {
331-
if let Some(Group::Prelude(prelude)) = symbol_db.groups.first() {
332-
let symbol_id_range = SymbolIdRange::prelude(prelude.symbol_definitions.len());
331+
verbose_timing_phase!("Update symdef resolutions");
333332

334-
for (local_index, def_info) in prelude.symbol_definitions.iter().enumerate() {
335-
let SymbolPlacement::DefsymSymbol(target_name) = def_info.placement else {
336-
continue;
337-
};
333+
for group in &symbol_db.groups {
334+
let mut symbol_id = group.symbol_id_range().start();
338335

339-
let symbol_id = symbol_id_range.offset_to_id(local_index);
340-
if !symbol_db.is_canonical(symbol_id) {
341-
continue;
336+
match group {
337+
Group::Prelude(prelude) => {
338+
for def_info in &prelude.symbol_definitions {
339+
update_defsym_symbol_resolution(symbol_id, def_info, symbol_db, resolutions)?;
340+
symbol_id = symbol_id.next();
341+
}
342342
}
343-
344-
let Some(target_symbol_id) = symbol_db
345-
.get_unversioned(&UnversionedSymbolName::prehashed(target_name.as_bytes()))
346-
else {
347-
return Err(symbol_db.missing_defsym_target_error(def_info.name, target_name));
348-
};
349-
350-
if let Some(target_value) = resolutions[target_symbol_id.as_usize()]
351-
.as_ref()
352-
.map(|r| r.raw_value)
353-
&& let Some(resolution) = &mut resolutions[symbol_id.as_usize()]
354-
{
355-
resolution.raw_value = target_value;
343+
Group::LinkerScripts(scripts) => {
344+
for script in scripts {
345+
for def_info in &script.parsed.symbol_defs {
346+
update_defsym_symbol_resolution(
347+
symbol_id,
348+
def_info,
349+
symbol_db,
350+
resolutions,
351+
)?;
352+
symbol_id = symbol_id.next();
353+
}
354+
}
356355
}
356+
Group::Objects(_) | Group::Epilogue(_) => {}
357357
}
358358
}
359359

360360
Ok(())
361361
}
362362

363+
fn update_defsym_symbol_resolution(
364+
symbol_id: SymbolId,
365+
def_info: &InternalSymDefInfo,
366+
symbol_db: &SymbolDb,
367+
resolutions: &mut [Option<Resolution>],
368+
) -> Result {
369+
let SymbolPlacement::DefsymSymbol(target_name) = def_info.placement else {
370+
return Ok(());
371+
};
372+
373+
if !symbol_db.is_canonical(symbol_id) {
374+
return Ok(());
375+
}
376+
377+
let Some(target_symbol_id) =
378+
symbol_db.get_unversioned(&UnversionedSymbolName::prehashed(target_name.as_bytes()))
379+
else {
380+
return Err(symbol_db.missing_defsym_target_error(def_info.name, target_name));
381+
};
382+
383+
if let Some(target_value) = resolutions[target_symbol_id.as_usize()]
384+
.as_ref()
385+
.map(|r| r.raw_value)
386+
&& let Some(resolution) = &mut resolutions[symbol_id.as_usize()]
387+
{
388+
resolution.raw_value = target_value;
389+
}
390+
391+
Ok(())
392+
}
393+
363394
/// Update resolutions for all dynamic symbols that our output file defines.
364395
fn update_dynamic_symbol_resolutions(
365396
layouts: &[GroupLayout],
@@ -3400,37 +3431,27 @@ impl<'data> PreludeLayoutState<'data> {
34003431
);
34013432
}
34023433

3403-
self.assign_defsym_flags(resources);
3434+
self.mark_defsyms_as_used(resources);
34043435

34053436
Ok(())
34063437
}
34073438

3408-
fn assign_defsym_flags(&self, resources: &GraphResources) {
3409-
let needs_dynsym = resources.symbol_db.output_kind.needs_dynsym();
3439+
/// Mark defsyms from the command-line as being directly referenced so that we emit the symbols
3440+
/// even if nothing in the code references them.
3441+
fn mark_defsyms_as_used(&self, resources: &GraphResources) {
34103442
for (index, def_info) in self.internal_symbols.symbol_definitions.iter().enumerate() {
34113443
let symbol_id = self.symbol_id_range.offset_to_id(index);
34123444
if !resources.symbol_db.is_canonical(symbol_id) {
34133445
continue;
34143446
}
34153447

34163448
match def_info.placement {
3417-
SymbolPlacement::DefsymAbsolute(_) => {
3449+
SymbolPlacement::DefsymAbsolute(_) | SymbolPlacement::DefsymSymbol(_) => {
34183450
resources
34193451
.per_symbol_flags
34203452
.get_atomic(symbol_id)
34213453
.or_assign(ValueFlags::DIRECT);
34223454
}
3423-
SymbolPlacement::DefsymSymbol(_) => {
3424-
let flags_to_set = if needs_dynsym {
3425-
ValueFlags::DIRECT | ValueFlags::EXPORT_DYNAMIC
3426-
} else {
3427-
ValueFlags::DIRECT
3428-
};
3429-
resources
3430-
.per_symbol_flags
3431-
.get_atomic(symbol_id)
3432-
.or_assign(flags_to_set);
3433-
}
34343455
_ => {}
34353456
}
34363457
}

libwild/src/parsing.rs

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rayon::iter::ParallelIterator;
2828

2929
pub(crate) fn parse_input_files<'data>(
3030
inputs: &[InputBytes<'data>],
31-
mut linker_scripts: Vec<ProcessedLinkerScript<'data>>,
31+
linker_scripts: Vec<ProcessedLinkerScript<'data>>,
3232
args: &'data Args,
3333
output_kind: OutputKind,
3434
) -> Result<ParsedInputs<'data>> {
@@ -47,12 +47,7 @@ pub(crate) fn parse_input_files<'data>(
4747
},
4848
);
4949

50-
verbose_timing_phase!("Count symbols");
51-
5250
let objects = objects?;
53-
let mut prelude = prelude;
54-
55-
move_linker_script_defsyms_to_prelude(&mut prelude, &mut linker_scripts);
5651

5752
let num_symbols = count_symbols(&prelude, &objects, &linker_scripts);
5853

@@ -262,29 +257,13 @@ impl<'data> Prelude<'data> {
262257
}
263258
}
264259

265-
fn move_linker_script_defsyms_to_prelude<'data>(
266-
prelude: &mut Prelude<'data>,
267-
linker_scripts: &mut [ProcessedLinkerScript<'data>],
268-
) {
269-
for script in linker_scripts {
270-
script.symbol_defs.retain(|def| {
271-
let is_defsym = matches!(
272-
def.placement,
273-
SymbolPlacement::DefsymAbsolute(_) | SymbolPlacement::DefsymSymbol(_)
274-
);
275-
if is_defsym {
276-
prelude.symbol_definitions.push(*def);
277-
}
278-
!is_defsym
279-
});
280-
}
281-
}
282-
283260
fn count_symbols(
284261
prelude: &Prelude,
285262
objects: &[ParsedInputObject],
286263
linker_scripts: &[ProcessedLinkerScript],
287264
) -> usize {
265+
verbose_timing_phase!("Count symbols");
266+
288267
let in_objects = objects.iter().map(|o| o.num_symbols()).sum::<usize>();
289268

290269
let in_linker_scripts = linker_scripts

0 commit comments

Comments
 (0)