Skip to content

ld symbols not found on c-style FFI union #30290

Closed
@daschl

Description

@daschl

Hi folks,

mainly tested on 1.4.0, but I also tested nightly.

this may be a compiler bug, but I'm not sure. So here is what I know is going on. I have the following code which was generated by crabtw/bindgen and is intended to work over a union in a c library (part of the relevant code to not make it too noisy):

#[repr(C)]
struct TopologyObjectAttributes {
    _bindgen_data_: [u64; 5usize],
}

impl TopologyObjectAttributes {
    pub unsafe fn cache(&mut self) -> *mut TopologyObjectCacheAttributes {
        let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
        ::std::mem::transmute(raw.offset(0))
    }
    pub unsafe fn group(&mut self) -> *mut TopologyObjectGroupAttributes {
        let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
        ::std::mem::transmute(raw.offset(0))
    }
    pub unsafe fn pcidev(&mut self) -> *mut TopologyObjectPCIDevAttributes {
        let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
        ::std::mem::transmute(raw.offset(0))
    }
    pub unsafe fn bridge(&mut self) -> *mut TopologyObjectBridgeAttributes {
        let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
        ::std::mem::transmute(raw.offset(0))
    }
    pub unsafe fn osdev(&mut self) -> *mut TopologyObjectOSDevAttributes {
        let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
        ::std::mem::transmute(raw.offset(0))
    }
}

#[repr(C)]
pub struct TopologyObjectCacheAttributes {
    pub size: c_ulonglong,
    pub depth: c_uint,
    pub linesize: c_uint,
    pub associativity: c_int,
    pub _type: TopologyObjectCacheType,
}

impl TopologyObjectCacheAttributes {
    pub fn size(&self) -> u64 {
        self.size
    }

    pub fn depth(&self) -> u32 {
        self.depth
    }
}

I'm showing only the impl for the cache part, but the other union variants work exactly the same way. The struct fields are public in the cache one for testing purposes, of course ideally I only have the getters. Now I have some code which does its unsafe job to dereference the pointers and ultimately get to the members of the struct.

    pub fn cache_attributes(&self) -> Option<&TopologyObjectCacheAttributes> {
        let cache_ptr = unsafe { (*self.attr).cache() };
        if cache_ptr.is_null() {
            None
        } else {
            unsafe { Some(&*cache_ptr) }
        }
    }

This is called like:

p.cache_attributes().unwrap().size();

Now here comes the important stuff. When I call it like this, the compiler fails on linking:

note: ld: warning: directory not found for option '-L/Users/michael/rust/hwloc-rs/.rust/lib/x86_64-apple-darwin'
ld: warning: directory not found for option '-L/Users/michael/rust/hwloc-rs/lib/x86_64-apple-darwin'
Undefined symbols for architecture x86_64:
  "topology_object::TopologyObjectCacheAttributes::size::h5726f74039bc15c7uMa", referenced from:
      main::hf733474fad67530eiaa in processor_cache.0.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

But when I change it to direct struct member access (not going through the getter) it works! So this compiles fine and runs as expected in my test code:

p.cache_attributes().unwrap().size;

I'm not an expert in rust so I have a hard time providing a smaller test case. If someone wants to run the code you can clone the repo and run the example (https://github.com/daschl/hwloc-rs/blob/master/examples/processor_cache.rs#L20) - $ cargo run --example processor_cache.

Just make sure to have the hwloc library installed (1.11.1, from here https://www.open-mpi.org/software/hwloc/v1.11/), just plain configure, make, sudo make install.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binaries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions