-
-
Notifications
You must be signed in to change notification settings - Fork 111
feat: Support -z pack-relative-relocs without actual packing
#1701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 72 commits
Commits
Show all changes
83 commits
Select commit
Hold shift + click to select a range
aef49fe
initial impl
mati865 fb08959
Renames
mati865 1aba2b6
Emit required version for glibc
mati865 540b112
Write addend into value
mati865 24e0933
Don't write erroneous section link
mati865 d699ceb
Sort relr entries
mati865 3e21426
Make the constants nicer
mati865 0b00c39
Fix wrong symbol versions when there are multiple deps with versions
mati865 87e82a7
Unskip Mold test
mati865 e4253a3
simplify glibc symbol handling
mati865 73bb142
move glibc special symbol writing to the end
mati865 74414d9
Address review feedback
mati865 627a32d
Simplify the conditions
mati865 09b9eef
Fix missed rename
mati865 0876ccb
clean up
mati865 3ab8395
wip: almost works with a single thread and input
mati865 7d26d6b
Proper output ordering (threads and multiple outputs still borked)
mati865 cba54ec
Use OutputSectionPartMap
mati865 d73dcfe
nicer printing
mati865 b333483
hack: use offsets to split output buffer
mati865 88bb03c
remove debug prints
mati865 a73f5d4
fix todo
mati865 4ffd217
wip: try to estimate how much size we can save
mati865 1c146a0
also print chunks with single relocation
mati865 73b1f36
remove saving estimation, the assumptions were bad
mati865 f532714
test: add a simple test
mati865 a4aadd3
remove borked saving estimation
mati865 e2bd220
fix: don't emit RELR for odd offset relocs
mati865 cb8c389
feat: handle RELR in linker-diff
mati865 98bc6a8
fix: ignore pack-relative-relocs unless amd64 or aarch64
mati865 65bf4a1
Remove unnecessary diffignores
mati865 bfc0924
undo the hacks
mati865 655a51a
use new object constatns
mati865 9b616ff
Undo accidental change
mati865 821b8f2
wip: try David's suggestion
mati865 837a214
test: extend with constructors
mati865 aa0ce41
wip: add more prints
mati865 c7bea63
fix allocation verifier
mati865 c70a746
remove failed attempt leftovers
mati865 d7ef128
test: format
mati865 86bc266
back to the offsets
mati865 78589bf
reset packing status when section changes
mati865 f150f44
disable prints
mati865 f55b55a
test: avoid AArch64 failure
mati865 c2f0b1b
enable relr on loongarch
mati865 57695a6
test: it doesn't use glibc
mati865 c6b6669
start cleanup, remove packing
mati865 143f451
cleanup constants
mati865 5a49a07
cleanup remove RelrWriter
mati865 560fe73
cleanup common fns and structs
mati865 b401dab
plumb Args through abstractions
mati865 99f38dc
cleanup the cleanups
mati865 0a13577
address TODO
mati865 16f6fb6
cleanup unnecessary unwrap
mati865 e303dff
Add comment
mati865 7a6790d
add TODO
mati865 537591d
Revert "Unskip Mold test"
mati865 7fc9bd6
test: skip on Ubuntu 24.04
mati865 f0ddd86
test: try to fix openSUSE error
mati865 4096e58
test: assert existence of relr section and tags
mati865 fe60c56
test: add comments
mati865 05b217c
Remove wip change that was suppsed to be removed
mati865 9ae6790
test: add glibc integration scenario
mati865 49d1fcf
linker-diff: remove unuseful comments
mati865 381b89a
chore: add comment to `write_address_relocation`
mati865 a6e3449
Remove old version impl
mati865 1e49aab
wip: add half baked attempts
mati865 11f2613
wip: dunno why this one works but not create_linker_defined_symbols
mati865 db54cf4
cleanup call sites of `write_address_relocation`
mati865 6ed8f19
Revert "Revert "Unskip Mold test""
mati865 d097056
test: add glibc requirement
mati865 c2f8719
wip: version import
mati865 45f1b7e
import whole symbol
mati865 8ad3c46
test: fmt
mati865 efc88aa
test:add explicit PIE
mati865 9556386
fix: reenable relr for RV64
mati865 e6ea553
test: use LLD instead
mati865 2a67d24
cleanup: revert unnecessary changes
mati865 630e076
fix comments
mati865 fcf1830
rename fn
mati865 d6a98ee
Oops, add help text
mati865 566bc27
merge main
mati865 74a4842
fmt
mati865 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,6 +151,7 @@ pub(crate) type SectionHeader = object::elf::SectionHeader64<LittleEndian>; | |
| pub(crate) type SymtabEntry = object::elf::Sym64<LittleEndian>; | ||
| pub(crate) type DynamicEntry = object::elf::Dyn64<LittleEndian>; | ||
| pub(crate) type Rela = object::elf::Rela64<LittleEndian>; | ||
| pub(crate) type Relr = object::elf::Relr64<LittleEndian>; | ||
| pub(crate) type GnuHashHeader = object::elf::GnuHashHeader<LittleEndian>; | ||
| pub(crate) type Verdef = object::elf::Verdef<LittleEndian>; | ||
| pub(crate) type Verdaux = object::elf::Verdaux<LittleEndian>; | ||
|
|
@@ -549,7 +550,7 @@ impl platform::Platform for Elf { | |
| ) -> Result<Self::DynamicLayoutExt<'data>> { | ||
| let mut is_last_verneed = false; | ||
|
|
||
| if let Some(v) = state.format_specific_state.verneed_info.as_ref() | ||
| if let Some(v) = &state.format_specific_state.verneed_info | ||
| && v.version_count > 0 | ||
| { | ||
| memory_offsets.increment( | ||
|
|
@@ -803,13 +804,15 @@ impl platform::Platform for Elf { | |
| output_kind: OutputKind, | ||
| mem_sizes: &OutputSectionPartMap<u64>, | ||
| resolution: &layout::Resolution<Elf>, | ||
| args: &ElfArgs, | ||
| ) -> Result { | ||
| crate::elf_writer::verify_resolution_allocation( | ||
| output_sections, | ||
| output_order, | ||
| output_kind, | ||
| mem_sizes, | ||
| resolution, | ||
| args, | ||
| ) | ||
| } | ||
|
|
||
|
|
@@ -947,6 +950,15 @@ impl platform::Platform for Elf { | |
| elf_symbol_type: stt::TLS, | ||
| is_hidden: false, | ||
| }); | ||
|
|
||
| // When `-z pack-relative-relocs` is used, Glibc requires this special version to be | ||
| // defined. | ||
| if args.pack_relative_relocs { | ||
| symbols.add_symbol(InternalSymDefInfo::new( | ||
| SymbolPlacement::VersionImport, | ||
| b"GLIBC_ABI_DT_RELR", | ||
| )); | ||
| } | ||
| } | ||
|
|
||
| fn built_in_section_infos<'data>() | ||
|
|
@@ -1101,9 +1113,12 @@ impl platform::Platform for Elf { | |
|
|
||
| fn apply_non_addressable_indexes<'data, 'groups>( | ||
| symbol_db: &SymbolDb<'data, Self>, | ||
| counts: &NonAddressableCounts, | ||
| counts: &mut NonAddressableCounts, | ||
| indexes: &NonAddressableIndexes, | ||
| mem_sizes_iter: impl Iterator<Item = &'groups mut OutputSectionPartMap<u64>>, | ||
| ) { | ||
| counts.final_version_index = indexes.next_gnu_version_r_index - 1; | ||
|
|
||
| // If we were going to output symbol versions, but we didn't actually use any, then we drop | ||
| // all versym allocations. This is partly to avoid wasting unnecessary space in the output | ||
| // file, but mostly in order match what GNU ld does. | ||
|
|
@@ -1408,6 +1423,7 @@ impl platform::Platform for Elf { | |
| flags: ValueFlags, | ||
| mem_sizes: &mut OutputSectionPartMap<u64>, | ||
| output_kind: OutputKind, | ||
| args: &Self::Args, | ||
| ) { | ||
| let has_dynamic_symbol = flags.is_dynamic() || flags.needs_export_dynamic(); | ||
|
|
||
|
|
@@ -1421,14 +1437,22 @@ impl platform::Platform for Elf { | |
| } else if flags.is_interposable() && has_dynamic_symbol { | ||
| mem_sizes.increment(part_id::RELA_DYN_GENERAL, elf::RELA_ENTRY_SIZE); | ||
| } else if flags.is_address() && output_kind.is_relocatable() { | ||
| mem_sizes.increment(part_id::RELA_DYN_RELATIVE, elf::RELA_ENTRY_SIZE); | ||
| if args.pack_relative_relocs { | ||
| mem_sizes.increment(part_id::RELR_DYN, elf::RELR_ENTRY_SIZE); | ||
| } else { | ||
| mem_sizes.increment(part_id::RELA_DYN_RELATIVE, elf::RELA_ENTRY_SIZE); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if flags.needs_ifunc_got_for_address() { | ||
| mem_sizes.increment(part_id::GOT, elf::GOT_ENTRY_SIZE); | ||
| if output_kind.is_relocatable() { | ||
| mem_sizes.increment(part_id::RELA_DYN_RELATIVE, elf::RELA_ENTRY_SIZE); | ||
| if args.pack_relative_relocs { | ||
| mem_sizes.increment(part_id::RELR_DYN, elf::RELR_ENTRY_SIZE); | ||
| } else { | ||
| mem_sizes.increment(part_id::RELA_DYN_RELATIVE, elf::RELA_ENTRY_SIZE); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -1796,6 +1820,7 @@ impl platform::Platform for Elf { | |
| builder.add_section(output_section_id::GNU_VERSION_D); | ||
| builder.add_section(output_section_id::GNU_VERSION_R); | ||
| builder.add_section(output_section_id::RELA_DYN_RELATIVE); | ||
| builder.add_section(output_section_id::RELR_DYN); | ||
| builder.add_section(output_section_id::RELA_PLT); | ||
| builder.add_section(output_section_id::RODATA); | ||
| builder.add_section(output_section_id::EH_FRAME_HDR); | ||
|
|
@@ -2929,7 +2954,8 @@ pub(crate) const GOT_ENTRY_SIZE: u64 = 0x8; | |
| // TODO: Right now, both x86_64 and AArch64 have 16 byte long entries, but | ||
| // the size should be generic over A: Arch. | ||
| pub(crate) const PLT_ENTRY_SIZE: u64 = 0x10; | ||
| pub(crate) const RELA_ENTRY_SIZE: u64 = 0x18; | ||
| pub(crate) const RELA_ENTRY_SIZE: u64 = size_of::<Rela>() as u64; | ||
| pub(crate) const RELR_ENTRY_SIZE: u64 = size_of::<Relr>() as u64; | ||
|
|
||
| pub(crate) const SYMTAB_ENTRY_SIZE: u64 = size_of::<SymtabEntry>() as u64; | ||
| pub(crate) const GNU_VERSION_ENTRY_SIZE: u64 = size_of::<Versym>() as u64; | ||
|
|
@@ -3864,6 +3890,8 @@ pub(crate) struct NonAddressableCounts { | |
| pub(crate) verneed_count: u64, | ||
| /// The number of verdef records provided in version script. | ||
| pub(crate) verdef_count: u16, | ||
| /// LLD creates GLIBC_ABI_DT_RELR as the last version across all inputs, we mimic that. | ||
| pub(crate) final_version_index: u16, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this still needed?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops, thought I already removed it. |
||
| } | ||
|
|
||
| #[derive(Debug)] | ||
|
|
@@ -4484,6 +4512,14 @@ const SECTION_DEFINITIONS: [BuiltInSectionDetails; NUM_BUILT_IN_SECTIONS] = { | |
| kind: SectionKind::Secondary(output_section_id::RELA_DYN_RELATIVE), | ||
| ..DEFAULT_DEFS | ||
| }; | ||
| defs[output_section_id::RELR_DYN.as_usize()] = BuiltInSectionDetails { | ||
| kind: SectionKind::Primary(SectionName(RELR_DYN_SECTION_NAME)), | ||
| ty: sht::RELR, | ||
| section_flags: shf::ALLOC, | ||
| element_size: RELR_ENTRY_SIZE, | ||
| min_alignment: alignment::RELR_ENTRY, | ||
| ..DEFAULT_DEFS | ||
| }; | ||
| defs[output_section_id::RISCV_ATTRIBUTES.as_usize()] = BuiltInSectionDetails { | ||
| kind: SectionKind::Primary(SectionName(RISCV_ATTRIBUTES_SECTION_NAME)), | ||
| ty: sht::RISCV_ATTRIBUTES, | ||
|
|
@@ -4779,7 +4815,13 @@ fn process_relocation<'data, 'scope, A: Arch<Platform = Elf>, R: Relocation>( | |
| && flags.is_address() | ||
| { | ||
| if section_is_writable { | ||
| common.allocate(part_id::RELA_DYN_RELATIVE, elf::RELA_ENTRY_SIZE); | ||
| // Uneven offsets mean bitmaps in RELR, so we need to fall back to RELA for | ||
| // them. | ||
| if resources.symbol_db.args.pack_relative_relocs && rel.offset().is_multiple_of(2) { | ||
| common.allocate(part_id::RELR_DYN, elf::RELR_ENTRY_SIZE); | ||
| } else { | ||
| common.allocate(part_id::RELA_DYN_RELATIVE, elf::RELA_ENTRY_SIZE); | ||
| } | ||
| } else if !is_debug_section { | ||
| bail!( | ||
| "Cannot apply relocation {} to read-only section. \ | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do the other linkers just ignore the flag when linking for riscv64? Could perhaps do with a comment here saying whether we're matching the behaviour of other linkers, or whether this is something that we just don't support. I'm assuming we shouldn't error when this flag is requested for riscv64?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I had tested riscv64 only via the integration test which hides the warning from GNU ld because it linked successfully, and failed on the assertions.
If I link manually, on both Arch and Ubuntu 25.10 I get:
/usr/lib/gcc/riscv64-linux-gnu/15.1.0/../../../../riscv64-linux-gnu/bin/ld: warning: -z pack-relative-relocs ignored.LLD on the other hand enables it, guess we want to match LLD in that case. I'll update it.