Inline assembly not produced when linking with main() file clang - c

I have the following code with an inline assembly in C:
#include <stdlib.h>
#include <stdio.h>
__attribute__((noinline))
int *get_indecies(int *padding, int pad_size, int size, int alias_type);
int *get_indecies(int *padding, int pad_size, int size, int alias_type){
int *indecies = (int *)malloc(size*sizeof(int));
asm("dsb sy\n\t");
return indecies;
}
At the bottom I the inline is inserted...
When I produce the object code using (cross compilation for aarch64) I have the inline inserted:
.....
1f0: d5033f9f dsb sy
1f4: aa1f03e1 mov x1, xzr
......
when I link this binary with my main file using:
clang verification.c get_indecies.o -I "/home/[name]/gem5/include" -L "/home/[name]/gem5/util/m5/build/arm64/out" -lm5 -lc -O0 -static -target aarch64-linux-gnu -o verfication-base-m5
and then I do an object dump of this to check if the assembly instruction is present using:
aarch64-linux-gnu-objdump verification-base-m5 -S > assembly.s
The inline assembly does not exist.... Any ideas about what is happening in the linking stage that is removing this assembly instruction? The optimisation level is turned to 0 so I am not sure...
Thanks!

I re-ran the below line recently:
clang verification.c get_indecies.o -I "/home/[name]/gem5/include" -L "/home/[name]/gem5/util/m5/build/arm64/out" -lm5 -lc -O0 -static -target aarch64-linux-gnu -o verfication-base-m5
and then object dumped this and the inline assembly was present. Not sure what the bug was during the time but in my case it is resolved.

Related

How to fix ".c:6: undefined reference to 'printf'

I am freshman, I want to learn about ARM assembly language and using gnu toolchain so I decided to start with small project that mixes arm-assembly file and C file by gnu toolchain. My idea is calling a function that is defined in assembly file.
multi.S:
.globl multi
multi:
str fp,[sp,#-4]!
add fp,sp,#0
sub sp,sp,#12
str r0,[fp,#-8]
str r1,[fp,#-12]
ldr r3,[fp,#-8]
ldr r2,[fp,#-12]
mul r1,r2,r3
mov r3,r1
mov r0,r3
add sp,fp,#0
ldr fp,[sp],#4
bx lr
multi.c:
#include <stdio.h>
unsigned int multi(unsigned int a, unsigned int b);
int main(int argc, char *argv[]){
unsigned int x = multi(3,4);
printf("%u\n",x);
return 0;
}
Then I tried to link them together by using command as follows:
arm-none-eabi-gcc -g -c -o multi-arm.o multi.S
arm-none-eabi-gcc -g -c -o multi.o multi.c
arm-none-eabi-ld multi.o multi-arm.o -o multi.elf
But there's some errors occurred:
warning: can not find entry symbol _start; defaulting to 0000000082000000
=> I solved this problem by adding -lc --entry main and the warning message is gone.
multi.c:6: undefined reference to 'printf'. I am stuck with this error and it took me 2 hours searching for sulution but I still can't not fix it.
Above is my question.
Thank you all for reading.
Try this
arm-none-eabi-as -g -o multi-arm.o multi.S
arm-none-eabi-gcc -g -o multi.elf multi.c multi-arm.o
If you want to use the linker directly then you have to provide the path to the C library on the command line. Gcc knows where the library is (relative to where it executes from and was compiled for) when it calls the linker, but for some strange reason ld does not.

inline function definition in header vs source file

I am confused about how to inline functions in c (C99 onwards). In section 18.6 of "C programming, a modern approach" (K.N. King, 2nd edition), or for example 3 in this tutorial (under "Strategies for using inline functions"), the definition of an inline function is given in the header (.h) file, then the function is again listed as extern in a source (.c) file.
For example, what I am doing: in a header "stencil.h"
#ifindef _STENCIL_H
#define _STENCIL_H
inline double D1_center_2ndOrder(double vp1, double vm1, double dr)
{
return (vp1-vm1) / (2.0 * dr) ;
}
#endif
Then in a matching source file "stencil.c" one defines
#include "stencil.h"
extern double D1_center_2ndOrder(double vp1, double vm1, double dr) ;
I did this, and then in a file "main.c" I called average:
#include <stdio.h>
#include <stdlib.h>
#include "stencil.h"
int main(int argc, char *argv[])
{
double vp1 = 1 ;
double vp2 = 2 ;
dr = 0.1 ;
double der_v = D1_center_2ndOrder(vp1, vm1, dr) ;
printf("der_v\t%f\n", der_v) ;
return 0 ;
}
I compile everything with the following makefile
CC = gcc
CFLAGS = -Wall -lm -std=gnu11
OBJECTS = main.o stencil.o
DEPS_MAIN = stencil.h
test: $(OBJECTS)
$(CC) -o collapse $(OBJECTS) $(CFLAGS)
main.o: main.c $(DEPS_MAIN)
$(CC) -c main.c
stencil.o: stencil.c stencil.h
$(CC) -c stencil.c
And I then get the following compiler error:
gcc -c main.c
gcc -c stencil.c
gcc -o test main.o stencil.o -Wall -lm -std=gnu11
stencil.o: In function `D1_center_2ndOrder':
stencil.c:(.text+0x0): multiple definition of `D1_center_2ndOrder'
main.o:main.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [collapse] Error 1
When I define the function in the .c source file "stencil.c" and declare it in the header file I do not get the above error. The version of gcc I am using is
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28).
My questions are:
(1) Why then does "C programming, a modern approach" and the tutorials on inlining functions that I find online suggest defining the function in the header file and listing it again as extern in a source file? Doing so for the above gives me a compiler error.
(2) When I declare the inline function in a header file then define as extern in a source file, will the compiler still inline my function?
You are using a portable strategy based on standard C99 (and more recent), which is entirely correct.
It is failing because you invoke gcc with its default -std setting, which for GCC 4.8.5 effectively tells it to use its legacy semantics and not standard C11 semantics. The default value for -std was gnu90 in version 4.8.5. In version 5, it was changed to gnu11, which implements C99/C11 inline semantics.
You're using default settings because your Makefile does not include $(CFLAGS) in the compile recipes; only in the final link recipe. (You can see that in the commands printed out by make).
While -std=gnu11 should work, it would be better to use -std=c11 instead. And consider upgrading to a more recent GCC version.
You need to pass the standard-version flag while compiling. It's not doing any good when you pass it in the linking stage.
So your makefile should be something like:
CC = gcc
CFLAGS = -Wall -std=gnu11
LDFLAGS = -lm
OBJECTS = main.o stencil.o
DEPS_MAIN = stencil.h
test: $(OBJECTS)
$(CC) -o collapse $(OBJECTS) $(LDFLAGS)
main.o: main.c $(DEPS_MAIN)
$(CC) -c main.c $(CFLAGS)
stencil.o: stencil.c stencil.h
$(CC) -c stencil.c $(CFLAGS)
I've tested your example with this shellscript:
#!/bin/sh -eu
cat > stencil.h <<EOF
#ifndef _STENCIL_H
#define _STENCIL_H
inline double D1_center_2ndOrder(double vp1, double vm1, double dr)
{
return (vp1-vm1) / (2.0 * dr) ;
}
#endif
EOF
cat > stencil.c <<EOF
#include "stencil.h"
extern double D1_center_2ndOrder(double vp1, double vm1, double dr) ;
EOF
cat > main.c <<EOF
#include <stdio.h>
#include <stdlib.h>
#include "stencil.h"
int main(int argc, char *argv[])
{
double vp1 = 1 ;
double vp2 = 2 ;
double dr = 0.1 ;
double vm1 = 0;
double der_v = D1_center_2ndOrder(vp1, vm1, dr) ;
printf("der_v\t%f\n", der_v) ;
return 0 ;
}
EOF
: ${CC:=gcc}
set -x
gcc -c main.c -std=c99
gcc -c stencil.c -std=c99
gcc -o test main.o stencil.o -lm
and gcc 4.6.4 and it's working fine, as long as the compilations (rather than the linking command) get at least -std=c99 (It's not working with 4.6.4's defaults).
(Side note: the header guard shouldn't start with an underscore and an uppper-case letter.)

How to combine LTO with symbol versioning

I would like to compile a shared library using both symbol versioning and link-time optimization (LTO). However, as soon as I turn on LTO, some of the exported symbols vanish. Here is a minimal example:
Start by defining two implementations of a function fun:
$ cat fun.c
#include <stdio.h>
int fun1(void);
int fun2(void);
__asm__(".symver fun1,fun#v1");
int fun1() {
printf("fun1 called\n");
return 1;
}
__asm__(".symver fun2,fun##v2");
int fun2() {
printf("fun2 called\n");
return 2;
}
Create a version script to ensure that only fun is exported:
$ cat versionscript
v1 {
global:
fun;
local:
*;
};
v2 {
global:
fun;
} v1;
First attempt, compile without LTO:
$ gcc -o fun.o -Wall -Wextra -O2 -fPIC -c fun.c
$ gcc -o libfun.so.1 -shared -fPIC -Wl,--version-script,versionscript fun.o
$ nm -D --with-symbol-versions libfun.so.1 | grep fun
00000000000006b0 T fun##v2
0000000000000690 T fun#v1
..exactly as it should be. But if I compile with LTO:
$ gcc -o fun.o -Wall -Wextra -flto -O2 -fPIC -c fun.c
$ gcc -o libfun.so.1 -flto -shared -fPIC -Wl,--version-script,versionscript fun.o
$ nm -D --with-symbol-versions libfun.so.1 | grep fun
..no symbols exported anymore.
What am I doing wrong?
WHOPR Driver Design gives some strong hints to what is going on. The function definitions fun1 and fun2 are not exported according to the version script. The LTO plugin is able to use this information, and since GCC does not peek into the asm directives, it knows nothing about the .symver directive, and therefore removes the function definition.
For now, adding __attribute__ ((externally_visible)) is the workaround for this. You also need to build with -flto-partition=none, so that the .symver directives do not land by accident in a different intermediate assembler file than the function definition (where it will not have the desired effect).
GCC PR 48200 tracks an enhancement request for symbol versioning at the compiler level, which would likely address this issue as well.
It looks like my externally_visible fix works. This is:
#define DLLEXPORT __attribute__((visibility("default"),externally_visible))
DLLEXPORT int fun1(void);
Also see: https://gcc.gnu.org/onlinedocs/gccint/WHOPR.html
But I think your versionscript is wrong.
If I take out the visibility overrides and change your versionscript by adding fun1 and fun2 then it works. Like:
v1 {
global:
fun; fun1;
local:
*;
};
v2 {
global:
fun; fun2;
} v1;
The symbol alias targets have to be visible as well as the alias.
I just hit the same problem - so thank you for asking this. However I've found it to be more clean to use __attribute__((used)). Since gcc is not scanning the top level assembler, it can't figure out that fun1 and fun2 are being used ... so it removes them. So it looks to me that changing definition to:
__asm__(".symver fun1,fun#v1");
int __attribute__((used)) fun1() {
printf("fun1 called\n");
return 1;
}
should be sufficient.

Linking two object files together causes segmentation fault 11

I am experimenting with externs and various methods of linking to better understand the linking process.
I have three files:
foo.c:
#include "foo.h"
int a = 4;
test.c:
#include <stdio.h>
#include "foo.h"
int main(int, char**);
int mymain();
int mymain() {
main(0, 0);
printf("test\r\n");
return 0;
}
int main(int argc, char** argv) {
printf("extern a has %d\r\n", a);
return 0;
}
foo.h:
extern int a; // defined in foo.c
If I build each file together and link at compile time using gcc like this:
gcc *.c -o final.bin
I can execute final.bin as:
./final.bin
and get expected output
extern a has 4
However, if I compile (but don't link) test.c and foo.c separately, then try and link the object files together at runtime to produce a binary, I get a segmentation fault 11 (which from what I can gather is some generic memory corruption bug like a normal segfault(?)
Here is my makefile I'm using to compile and link separately. Note I am specifying my own entry point and linking against libc to get printf()...
all: test.o foo.o
#echo "Making all..."
ld test.o foo.o -o together.bin -lc -e _mymain
test.o: test.c
#echo "Making test..."
gcc -c test.c -o test.o
foo.o: foo.c
#echo "Making foo..."
gcc -c foo.c -o foo.o
Output when running 'together.bin':
./together.bin
extern a has 4
test
Segmentation fault: 11
Perhaps my function signature for 'mymain' is wrong? My guess is that something is wrong with my 'myentry' usage.
Also, if anyone has any recommendations on good books for how linkers and loaders work, I am certainly in the market for one. I've heard mixed things about 'Linkers and Loaders', so I'm waiting on more opinions before I invest the time in that book in particular.
Thanks for any help on this... My understanding of linkers is sub-par to say the least.
Unless if you have a good reason to do so, just use gcc to link:
$ gcc test.o foo.o "-Wl,-e,_mymain" -o ./final.bin; ./final.bin
extern a has 4
test
gcc calls ld---though, with a few more arguments than you are providing in your example. If you want to know exactly how gcc invokes ld, use the -v option. Example:
$ gcc -v test.o foo.o "-Wl,-e,_mymain" -o ./final.bin
Apple LLVM version 8.0.0 (clang-800.0.38)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.12.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -o ./final.bin test.o foo.o -e _mymain -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin/libclang_rt.osx.a

gcc-linux-gnueabi-arm error undefined reference to `main'

I am trying to generate assembly and executable of a simple neon-based c code. The code is,
#include <arm_neon.h>
void NeonTest(short int * __restrict a, short int * __restrict b, short int * __restrict z)
{
int i;
for (i = 0; i < 200; i++) {
z[i] = a[i] * b[i];
}
}
First, I am going for the assembly to calculate the neon instructions,
arm-linux-gnueabi-gcc -O2 -march=armv7-a -mtune=cortex-a9 -ftree-vectorize -mhard-float -mfloat-abi=softfp -mfpu=neon -S neon_test.c -o nt.s
Then I am converting the nt.s file to object file.
arm-linux-gnueabi-gcc -O2 -march=armv7-a -mtune=cortex-a9 -ftree-vectorize -mhard-float -mfloat-abi=softfp -mfpu=neon -c nt.s -o nt.o
Finally, for the executable I do,
arm-linux-gnueabi-gcc -O2 -march=armv7-a -mtune=cortex-a9 -ftree-vectorize -mhard-float -mfloat-abi=softfp -mfpu=neon nt.o -o nt
I get the error,
/usr/lib/gcc-cross/arm-linux-gnueabi/4.7/../../../../arm-linux-gnueabi/lib/crt1.o: In function `_start':
(.text+0x34): undefined reference to `main'
collect2: error: ld returned 1 exit status
I am using Ubuntu 14LTS on Intel system.
You're not including the C file that contains main() when compiling, so the linker isn't seeing it
You need to add it:
arm-linux-gnueabi-gcc -O2 -march=armv7-a -mtune=cortex-a9 -ftree-vectorize -mhard-float -mfloat-abi=softfp -mfpu=neon nt.o main.o -o nt
where main.o is also created following the same step as neon.o
Every program needs a starting point so the computer knows where to begin execution. In C/C++, the starting point is the beginning of the function int main. Give your program an int main by either linking your object file to an object file with int main, or adding one in this code.
To add main in your code, beneath your function definition, try
int main()
{
NeonTest(/* your parameters */);
}

Resources