Repository navigation
fix: improve linker script expression section semantics - #2731
vishruth-thimmaiah wants to merge 6 commits into
Conversation
Signed-off-by: Vishruth Thimmaiah <vishruththimmaiah@gmail.com>
davidlattimore
left a comment
There was a problem hiding this comment.
Here are some extra related tests that currently fail:
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/absolute-arithmetic.ld b/wild/tests/sources/elf/linker-script-expression-sections/absolute-arithmetic.ld
new file mode 100644
index 0000000000..d221ad17da
--- /dev/null
+++ b/wild/tests/sources/elf/linker-script-expression-sections/absolute-arithmetic.ld
@@ -0,0 +1,13 @@
+ENTRY(_start)
+SECTIONS {
+ .text 0x10000 : {
+ section_start = .;
+ *(.text*)
+ }
+}
+
+/* These operations produce absolute values even with a section operand. */
+product = section_start * 2;
+quotient = section_start / 2;
+shifted = section_start >> 1;
+reverse_difference = 0x20000 - section_start;
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/addr-alias.ld b/wild/tests/sources/elf/linker-script-expression-sections/addr-alias.ld
new file mode 100644
index 0000000000..7463c19edc
--- /dev/null
+++ b/wild/tests/sources/elf/linker-script-expression-sections/addr-alias.ld
@@ -0,0 +1,9 @@
+ENTRY(_start)
+SECTIONS {
+ .text 0x10000 : {
+ *(.text*)
+ /* ADDR retains the referenced section, including through arithmetic. */
+ section_addr = ADDR(.text);
+ after_addr = section_addr + 0x10;
+ }
+}
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c b/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c
new file mode 100644
index 0000000000..114b4c89d5
--- /dev/null
+++ b/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c
@@ -0,0 +1,37 @@ void _start(void) {}
+//#AbstractConfig:base
+//#RunEnabled:false
+//#DiffEnabled:false
+//#ReferenceLinkers:bfd
+
+//#Config:addr-alias:base
+//#ReferenceLinkers:bfd,lld
+//#LinkArgs:-T ./addr-alias.ld
+//#ExpectSym:after_addr section=".text",address=0x10010
+//#ExpectSym:section_addr section=".text",address=0x10000
+
+//#Config:min-max-number:base
+//#LinkArgs:-T ./min-max-number.ld
+//#ExpectSym:min_right section=".text",address=0x10000
+//#ExpectSym:min_left section=".text",address=0x10000
+//#ExpectSym:max_right section=".text",address=0x10010
+//#ExpectSym:max_left section=".text",address=0x10010
+
+//#Config:min-max-location:base
+//#LinkArgs:-T ./min-max-location.ld
+//#ExpectSym:padded_end section=".text",address=0x10100
+
+//#Config:absolute-arithmetic:base
+//#ReferenceLinkers:bfd,lld
+//#LinkArgs:-T ./absolute-arithmetic.ld
+//#ExpectSym:product is_abs=true,address=0x20000
+//#ExpectSym:quotient is_abs=true,address=0x8000
+//#ExpectSym:shifted is_abs=true,address=0x8000
+//#ExpectSym:reverse_difference is_abs=true,address=0x10000
+
+//#Config:relative-plus-absolute:base
+//#LinkArgs:-T ./relative-plus-absolute.ld
+//#ExpectSym:absolute_offset is_abs=true,address=0x10
+//#ExpectSym:derived is_abs=true,address=0x10010
+//#ExpectSym:derived_reverse is_abs=true,address=0x10010
+
+void _start(void) {}
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/min-max-location.ld b/wild/tests/sources/elf/linker-script-expression-sections/min-max-location.ld
new file mode 100644
index 0000000000..fb8e396591
--- /dev/null
+++ b/wild/tests/sources/elf/linker-script-expression-sections/min-max-location.ld
@@ -0,0 +1,9 @@
+ENTRY(_start)
+SECTIONS {
+ .text 0x10000 : {
+ *(.text*)
+ /* The same conversion must work during early layout evaluation. */
+ . = MAX(., 0x100);
+ padded_end = .;
+ }
+}
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/min-max-number.ld b/wild/tests/sources/elf/linker-script-expression-sections/min-max-number.ld
new file mode 100644
index 0000000000..edfcd004b3
--- /dev/null
+++ b/wild/tests/sources/elf/linker-script-expression-sections/min-max-number.ld
@@ -0,0 +1,12 @@
+ENTRY(_start)
+SECTIONS {
+ .text 0x10000 : {
+ section_start = .;
+ *(.text*)
+ /* GNU ld compares section offsets with numeric operands here. */
+ min_right = MIN(section_start, 0x10);
+ min_left = MIN(0x10, section_start);
+ max_right = MAX(section_start, 0x10);
+ max_left = MAX(0x10, section_start);
+ }
+}
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/relative-plus-absolute.ld b/wild/tests/sources/elf/linker-script-expression-sections/relative-plus-absolute.ld
new file mode 100644
index 0000000000..7a3aa3490b
--- /dev/null
+++ b/wild/tests/sources/elf/linker-script-expression-sections/relative-plus-absolute.ld
@@ -0,0 +1,14 @@
+ENTRY(_start)
+absolute_offset = 0x10;
+
+SECTIONS {
+ .text 0x10000 : {
+ section_start = .;
+ *(.text*)
+ }
+}
+
+/* A named absolute symbol exercises Relative/Absolute, rather than
+ Relative/Number. GNU ld makes both sums absolute outside a section. */
+derived = section_start + absolute_offset;
+derived_reverse = absolute_offset + section_start;| let resolution = resolutions[canonical_symbol_id.as_usize()] | ||
| .as_mut() | ||
| .ok_or_else(|| redirect.missing_resolution(def_info.name))?; | ||
| if is_absolute && redirect.loc.relative_section_id().is_some() { |
There was a problem hiding this comment.
This function both reads and writes redirect.loc, making it a little hard to follow what's going on. Is there an alternative that would be more readable?
There was a problem hiding this comment.
I've added a Redirect::update_for_evaluated_value method here.
Signed-off-by: Vishruth Thimmaiah <vishruththimmaiah@gmail.com>
| } | ||
| } | ||
|
|
||
| if exp.assertions.is_abs { |
There was a problem hiding this comment.
Some of the tests have is_abs=false, but it looks like this will skip any check if that's the case
There was a problem hiding this comment.
Fixed, I've replaced any is_abs=false checks with an explicit section check.
| _section_layouts: &OutputSectionMap<OutputRecordLayout>, | ||
| op: impl FnOnce(u64, u64) -> Result<u64>, | ||
| ) -> Result<EvaluatedValue> { | ||
| let value_kind = if is_in_section { |
There was a problem hiding this comment.
Does it matter what type we produce for expressions like LOADADDR(.text) & 0xffff? Do we agree with the other linkers in that case with regard to whether the result is absolute to section-relative?
There was a problem hiding this comment.
lld and ld deviate on how they handle absolute results, and I was previously matching whichever linkers' behavior was more convenient. I've updated it to match bfd more closely.
Signed-off-by: Vishruth Thimmaiah <vishruththimmaiah@gmail.com>
| (ExpressionValueKind::Number, ExpressionValueKind::Number) => { | ||
| ExpressionValueKind::Number | ||
| } | ||
| (ExpressionValueKind::Relative(sec), _) | (_, ExpressionValueKind::Relative(sec)) => { |
There was a problem hiding this comment.
It looks like subtracting a relative offset from another relative offset should produce an absolute:
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c b/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c
index 086c2547af..41623d5217 100644
--- a/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c
+++ b/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c
@@ -17,6 +17,11 @@
//#ExpectSym:max_right section=".text",address=0x10010
//#ExpectSym:max_left section=".text",address=0x10010
+//#Config:nested-subtraction:base
+//#ReferenceLinkers:bfd,lld
+//#LinkArgs:-T ./nested-subtraction.ld
+//#ExpectSym:difference is_abs=true,address=0x20
+
//#Config:min-max-location:base
//#LinkArgs:-T ./min-max-location.ld
//#ExpectSym:padded_end section=".text",address=0x10100
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/nested-subtraction.ld b/wild/tests/sources/elf/linker-script-expression-sections/nested-subtraction.ld
new file mode 100644
index 0000000000..702b662e0d
--- /dev/null
+++ b/wild/tests/sources/elf/linker-script-expression-sections/nested-subtraction.ld
@@ -0,0 +1,9 @@
+ENTRY(_start)
+SECTIONS {
+ .text 0x10000 : {
+ section_start = .;
+ section_end = section_start + 0x20;
+ difference = MIN(section_end - section_start, LOADADDR(.text));
+ *(.text*)
+ }
+}There was a problem hiding this comment.
Fixed, along with a few other previously failing tests.
Signed-off-by: Vishruth Thimmaiah <vishruththimmaiah@gmail.com>
Signed-off-by: Vishruth Thimmaiah <vishruththimmaiah@gmail.com>
Signed-off-by: Vishruth Thimmaiah <vishruththimmaiah@gmail.com>
davidlattimore
left a comment
There was a problem hiding this comment.
Looks like cross-section expressions aren't doing the right thing:
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/cross-section-offsets.ld b/wild/tests/sources/elf/linker-script-expression-sections/cross-section-offsets.ld
new file mode 100644
index 0000000000..fa2f4bcf68
--- /dev/null
+++ b/wild/tests/sources/elf/linker-script-expression-sections/cross-section-offsets.ld
@@ -0,0 +1,12 @@
+ENTRY(_start)
+SECTIONS {
+ .data 0x20000 : {
+ data_start = .;
+ KEEP(*(.data*))
+ }
+ .text 0x10000 : {
+ cross_min = MIN(data_start, 0x10);
+ cross_mul = data_start * 2;
+ *(.text*)
+ }
+}
diff --git a/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c b/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c
index 28e5cb80b3..f989ee66c0 100644
--- a/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c
+++ b/wild/tests/sources/elf/linker-script-expression-sections/linker-script-expression-sections.c
@@ -17,6 +17,11 @@
//#ExpectSym:max_right section=".text",address=0x10010
//#ExpectSym:max_left section=".text",address=0x10010
+//#Config:cross-section-offsets:base
+//#LinkArgs:-T ./cross-section-offsets.ld
+//#ExpectSym:cross_min section=".data",address=0x20000
+//#ExpectSym:cross_mul section=".data",address=0x20000
+
//#Config:nested-subtraction:base
//#ReferenceLinkers:bfd,lld
//#LinkArgs:-T ./nested-subtraction.ld
This PR make a bunch of improvements to how different types of expressions(absolute, section relative, numbers) interact with each other. Fixes:
Symbols preserve their section indexes across redefinition.
Preserving section relativity across ternary, MIN, and MAX expressions
Logical, bitwise, and comparison operators producing absolute symbols