Repository: davidlattimore/wild (rust)

Issue:
Error: Symbol is in a section that we didn't load. Symbol: symbol `compute_value10` (76 local=5) in file #1025 (4/1) (/tmp/cc3sE5xh.o) (IFUNC | CAN_BYPASS_GOT) Section: `.text`
Noticed while isolating another issue:

```
$ cat snippet.c
static int return10() {
    return 10;
}

int compute_value10(void) __attribute__((ifunc ("resolve_compute_value10")));

static void *resolve_compute_value10(void) {
    return return10;
}
$ cat snippet2.c
int main() {
  return 0;
}
$ gcc snippet*.c -B ~/Programming/wild
WARNING: wild: --plugin /usr/lib64/gcc/x86_64-suse-linux/14/liblto_plugin.so is not yet supported
Error: Symbol is in a section that we didn't load. Symbol: symbol `compute_value10` (76 local=5) in file #1025 (4/1) (/tmp/ccdNDbYx.o) (IFUNC | CAN_BYPASS_GOT) Section: `.text`
collect2: error: ld returned 255 exit status
```

Pull request description:
Fix linking when an ifunc isn't referenced
Fixes #296

Patch:
diff --git a/libwild/src/layout.rs b/libwild/src/layout.rs
index 4281e01..51cf3f5 100644
--- a/libwild/src/layout.rs
+++ b/libwild/src/layout.rs
@@ -686,12 +686,13 @@ fn allocate_symbol_resolution(
     mem_sizes: &mut OutputSectionPartMap<u64>,
     output_kind: OutputKind,
 ) {
-    if value_flags.contains(ValueFlags::IFUNC) {
+    let mut r = resolution_flags.get();
+    if !r.is_empty() && value_flags.contains(ValueFlags::IFUNC) {
         resolution_flags.fetch_or(ResolutionFlags::GOT | ResolutionFlags::PLT);
+        r |= ResolutionFlags::GOT | ResolutionFlags::PLT;
     }
-    let resolution_flags = resolution_flags.get();
 
-    allocate_resolution(value_flags, resolution_flags, mem_sizes, output_kind);
+    allocate_resolution(value_flags, r, mem_sizes, output_kind);
 }
 
 /// Computes how much to allocation for a particular resolution. This is intended for debug
@@ -3503,7 +3504,8 @@ impl<'data> ObjectLayoutState<'data> {
                             return Ok(None);
                         }
                         bail!(
-                            "Symbol is in a section that we didn't load. Symbol: {} Section: {}",
+                            "Symbol is in a section that we didn't load. \
+                             Symbol: {} Section: {} Res: {resolution_flags}",
                             resources.symbol_db.symbol_debug(symbol_id),
                             section_debug(self.object, section_index),
                         );


Test patch:
diff --git a/wild/tests/sources/ifunc.c b/wild/tests/sources/ifunc.c
index cc2a270..32f9f82 100644
--- a/wild/tests/sources/ifunc.c
+++ b/wild/tests/sources/ifunc.c
@@ -6,7 +6,7 @@
 //#DiffIgnore:section.rela.plt.link
 
 //#Config:pie:default
-//#CompArgs:-fpie
+//#CompArgs:-fpie -ffunction-sections
 
 //#Config:no-pie:default
 //#CompArgs:-fno-pie
diff --git a/wild/tests/sources/ifunc1.c b/wild/tests/sources/ifunc1.c
index 973c748..6439069 100644
--- a/wild/tests/sources/ifunc1.c
+++ b/wild/tests/sources/ifunc1.c
@@ -2,7 +2,7 @@ extern int compute_value(void);
 
 int resolve_count = 0;
 
-static int return10() {
+static int return10(void) {
     return 10;
 }
 
@@ -13,7 +13,7 @@ static void *resolve_compute_value10(void) {
     return return10;
 }
 
-static int return32() {
+static int return32(void) {
     return 32;
 }
 
@@ -23,3 +23,13 @@ static void *resolve_compute_value32(void) {
     resolve_count++;
     return return32;
 }
+
+static int unused(void) {
+    return 20;
+}
+
+int compute_unused(void) __attribute__((ifunc ("resolve_compute_unused")));
+
+static void *resolve_compute_unused(void) {
+    return unused;
+}