Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions LINKER_SCRIPT_SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ end lists the features required to link the Linux kernel.
| `MIN(a, b)` | ✅ | |
| `MAX(a, b)` | ✅ | |
| Ternary operator (`condition ? a : b`) | ✅ | |
| `DEFINED(sym)` | 📅 | |
| `DEFINED(sym)` | | |
| `SIZEOF_HEADERS` | ✅ | |
| `SEGMENT_START(segment, default)` | ✅ | Supports `"text"`, `"data"`, `"bss"`, `"rodata"`; returns `-Ttext`/`-Tdata`/`-Tbss` override if provided, otherwise `default`; unknown segment names always return `default` |

Expand Down Expand Up @@ -122,6 +122,6 @@ see at a glance what remains before Wild can link the kernel.
| `CONSTRUCTORS` command | 📅 | |
| `PHDRS` command for explicit program header definition | 🧪 | The FILEHDR and PHDRS keywords aren't yet supported. |
| Ternary operator (`condition ? a : b`) | ✅ | |
| `DEFINED(sym)` function | 📅 | |
| `DEFINED(sym)` function | | |
| `SIZEOF_HEADERS` built-in symbol | ✅ | |
| `/DISCARD/` command | ✅ | |
3 changes: 3 additions & 0 deletions libwild/src/expression_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ pub(crate) fn evaluate_expression<'data, P: Platform>(
eval!(if_false)
}
}
Expression::Defined(name) => Ok(symbol_db
.get_unversioned(&UnversionedSymbolName::prehashed(name))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that this will do the correct thing if there are objects that reference, but don't define the symbol. Can you add a test for that? i.e. have an object that has a weak reference to the symbol.

.map_or(0, |_| 1)),
}
}

Expand Down
11 changes: 9 additions & 2 deletions libwild/src/linker_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ pub(crate) struct Phdr<'a> {
/// - Bitwise: &, |, ^, ~, <<, >>
/// - Logical: &&, ||
/// - Unary: -, !, ~
/// - Functions: SIZEOF, ALIGNOF, LENGTH, ORIGIN, ADDR, LOADADDR, ALIGN, MIN, MAX, SEGMENT_START
/// - Functions: SIZEOF, ALIGNOF, LENGTH, ORIGIN, ADDR, LOADADDR, ALIGN, MIN, MAX, SEGMENT_START,
/// DEFINED
/// - Numbers (hex/decimal), symbols, location counter (.)
/// - Parentheses for grouping
/// - Ternary operator (? :)
Expand Down Expand Up @@ -229,6 +230,7 @@ pub(crate) enum Expression<'a> {
Box<Expression<'a>>,
Box<Expression<'a>>,
),
Defined(&'a [u8]),
}

#[derive(Debug, PartialEq, Eq, Clone)]
Expand Down Expand Up @@ -261,7 +263,8 @@ impl<'a> Expression<'a> {
| Expression::Addr(_)
| Expression::Loadaddr(_)
| Expression::Symbol(_)
| Expression::SizeofHeaders => {}
| Expression::SizeofHeaders
| Expression::Defined(_) => {}
Expression::Add(l, r)
| Expression::Subtract(l, r)
| Expression::Multiply(l, r)
Expand Down Expand Up @@ -926,6 +929,10 @@ fn parse_identifier_or_function<'a>(input: &mut &'a BStr) -> winnow::Result<Expr
Box::new(default_expr),
))
}
b"DEFINED" => {
let symbol = parse_function_arg.parse_next(input)?;
Ok(Expression::Defined(symbol))
}
_ => Err(ContextError::default()),
}
} else if ident == b"SIZEOF_HEADERS" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
//#RunEnabled:false
//#DiffEnabled:false
void _start() {}

int symbol4 = 0x4000;
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
ENTRY(_start)

SECTIONS {
.text : { *(.text*) }
.text : {
*(.text*)
symbol3 = 0x3000;
}
.data : { *(.data*) }
.bss : { *(.bss*) }
}
Expand All @@ -27,3 +30,7 @@ ASSERT(symbol1 + symbol2 != symbol1 - symbol2, "symbol1 + symbol2 must not be sy
ASSERT(0xffffffff81000000 == (0xffffffff80000000 + (((symbol1 * 0x1000) + (symbol2 * 0x100 - 1)) & ~(0x200000 - 1))), "Incorrect Value");
ASSERT((5 > 4 ? !1 ? 3 : 5 : 4) == 5, "5 > 4 ? !1 ? 3 : 5 : 4 must be 5");
ASSERT((symbol1 > symbol2 ? symbol1 : symbol2) == MAX(symbol1, symbol2), "Expected MAX(symbol1, symbol2)");
ASSERT(DEFINED(symbol1), "symbol1 must be defined");
ASSERT(DEFINED(symbol3), "symbol3 must be defined");
ASSERT(DEFINED(symbol4), "symbol4 must be defined");
ASSERT(!DEFINED(symbol5), "symbol5 is not defined");
Loading