Skip to content
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

Static items can result in references to unexported symbols #13620

Closed
bkoropoff opened this issue Apr 19, 2014 · 0 comments · Fixed by #13906
Closed

Static items can result in references to unexported symbols #13620

bkoropoff opened this issue Apr 19, 2014 · 0 comments · Fixed by #13906
Labels
A-linkage Area: linking into static, shared libraries and binaries

Comments

@bkoropoff
Copy link
Contributor

Scenario

  • Crate 1 contains a struct with an extern fn field
  • Crate 1 contains a pub static item of that struct, with the field being initialized to a priv extern fn
  • Crate 2 contains a static item of the same struct which is initialized to the static item in crate 1
  • All crates are built as dylibs, and a program is linked against crate 2

Result

Crate 2 ends up referring directly to the priv extern fn in crate 1, which is not in the dynamic symbol table for the crate. The program fails to link.

Code

crate1.rs

pub struct Foo {
    pub foo: extern fn()
}

extern fn the_foo() {}

pub static FOO: Foo = Foo {
    foo: the_foo
};

crate2.rs

extern crate crate1;

pub static FOO2: crate1::Foo = crate1::FOO;

main.rs

extern crate crate2;

fn main() {
    (crate2::FOO2.foo)();
}

Makefile

CRATE1=$(shell rustc --crate-type=dylib --crate-file-name crate1.rs)
CRATE2=$(shell rustc --crate-type=dylib --crate-file-name crate2.rs)

all: main

$(CRATE1): crate1.rs
    rustc --crate-type=dylib $<

$(CRATE2): crate2.rs $(CRATE1)
    rustc --crate-type=dylib -L. $<

main: main.rs $(CRATE2)
    rustc -L. $<

clean:
    rm -f *.so main

.PHONY: clean all

Output

Excerpt of error:

....
note: .../rust-bug/libcrate2-c9f1a15a-0.0.so: error: undefined reference to 'the_foo::h33cb9568e97d6893haa::v0.0'
alexcrichton added a commit to alexcrichton/rust that referenced this issue May 2, 2014
This ensures that private functions exported through static initializers will
actually end up being public in the object file (so other objects can continue
to reference the function).

Closes rust-lang#13620
bors added a commit that referenced this issue May 3, 2014
This ensures that private functions exported through static initializers will
actually end up being public in the object file (so other objects can continue
to reference the function).

Closes #13620
bors added a commit to rust-lang-ci/rust that referenced this issue Jan 9, 2023
…r=Veykril

fix: check tail expressions more precisely in `extract_function`

Fixes rust-lang#13620

When extracting expressions with control flows into a function, we can avoid wrapping tail expressions in `Option` or `Result` when they are also tail expressions of the container we're extracting from (see rust-lang#7840, rust-lang#9773). This is controlled by `ContainerInfo::is_in_tail`, but we've been computing it by checking if the tail expression of the range to extract is contained in the container's syntactically last expression, which may be a block that contains both tail and non-tail expressions (e.g. in rust-lang#13620, the range to be extracted is not a tail expression but we set the flag to true).

This PR tries to compute the flag as precise as possible by utilizing `for_each_tail_expr()` (and also moves the flag to `Function` struct as it's more of a property of the function to be extracted than of the container).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants