global symbols converted to local symbols

I have a bitcode file x.bc. When I run llmv-nm on x.bc, it shows that a function f(), that I've written, is defined as a global function (text) object, i.e., llvm-nm shows it marked with a 'T'. I have converted x.bc to an executable with the following command: llvm-ld -native -o x.exe x.bc When I run nm on x.exe, it shows that f is now a local function (text) object, i.e., nm shows it marked with a 't'. Why is llvm-ld converting f() from a global function object to a local function object.

I believe that I need f() to be a global function object because I use LD_PRELOAD to load a library that make use of f().

Thanks,
Ryan

As a follow up, if I first convert x.bc to a c file using llc -march=c -o x.c x.bc, and then I use normal gcc to convert x.c to an executable, f() remains a global symbol. Is llvm-nm incorrectly converting the global symbols to local symbols?

Ryan M. Lefever wrote:

As a follow up, if I first convert x.bc to a c file using llc -march=c
-o x.c x.bc, and then I use normal gcc to convert x.c to an executable,
f() remains a global symbol. Is llvm-nm incorrectly converting the
global symbols to local symbols?

By default, llvm-ld converts all symbols to internal/static. Use -disable-internalize if you don't want this. Note that this will disable a lot of optimization.

-Chris

Ryan M. Lefever wrote:

I have a bitcode file x.bc. When I run llmv-nm on x.bc, it shows that a function f(), that I've written, is defined as a global function (text) object, i.e., llvm-nm shows it marked with a 'T'. I have converted x.bc to an executable with the following command: llvm-ld -native -o x.exe x.bc When I run nm on x.exe, it shows that f is now a local function (text) object, i.e., nm shows it marked with a 't'. Why is llvm-ld converting f() from a global function object to a local function object.
  

I suspect what is happening is that the internalize pass is being executed by llvm-ld because it believes that your program is now complete and that it is safe to mark globals as internal (which provides greater optimization opportunity).

There are several things you can do:

1) Run llvm-ld with the -disable-opt option to disable optimization. Use opt to optimize manually using the -internalize-<x> options to control what is internalized and what is not (see opt --help for more information).

2) If the native code library is one that you wrote, you can change the interface to pass a pointer to the global into the library as opposed to having the linker resolve the references.

-- John T.

Ryan M. Lefever wrote:

Ryan M. Lefever wrote:

I have a bitcode file x.bc. When I run llmv-nm on x.bc, it shows that a function f(), that I've written, is defined as a global function (text) object, i.e., llvm-nm shows it marked with a 'T'. I have converted x.bc to an executable with the following command: llvm-ld -native -o x.exe x.bc When I run nm on x.exe, it shows that f is now a local function (text) object, i.e., nm shows it marked with a 't'. Why is llvm-ld converting f() from a global function object to a local function object.

>
> As a follow up, if I first convert x.bc to a c file using llc -march=c
> -o x.c x.bc, and then I use normal gcc to convert x.c to an executable,
> f() remains a global symbol. Is llvm-nm incorrectly converting the
> global symbols to local symbols?

I believe your problem may be that llvm-ld by default runs the 'internalize' pass before running any other optimizations. What that pass does is mark any functions other than 'main' (or functions explicitly specified by the user) as 'internal'. This is done to allow other optimizations to modify the function signatures; many interprocedural optimizations refuse to touch non-internal functions.
If you want to disable this behavior entirely, pass -disable-internalize' to llvm-ld. If you want to disable it only for specific functions (recommended if you want to optimize your code) try -internalize-public-api-file=<filename> or -internalize-public-api-list=<list>.
If you use either of the latter two, make sure to put 'main' on the list as well; it doesn't look like 'internalize' does that automatically anymore if it's passed an explicit list.

Frits, John, and Chris,

Thanks for the help. Frits, the suggestion about using -internalize-public-api-file= worked great.

Regards,
Ryan