I have written a simple program fabs.c to display the absolute value of a floating point number.
#include <stdio.h>
#include <math.h>
int main(void)
{
float f;
printf("Enter a floating-point number: ");
scanf("%f", &f);
printf("Its absolute value is %f.\n", fabs(f));
return 0;
}
fabs() function requires including the math.h header file, but I compiled successfully without -lm option.
gcc fabs.c -o fabs
Even man fabs says link with -lm. But I don't know why I can compile it successfully without -lm.
If the manual says that you should link with -lm, then you should link with -lm. In this case your code is simple enough and the compiler is smart enough to inline it (because your system always uses the gcc built-in). Maybe it won't be able to in some cases. Some of the floating point function built-ins fall back to the library functions if they can't be trivially inlined (not fabs, but many others).
Manuals often tell you to do things that aren't strictly necessary in all cases because it's easier to say "do X" than to say "if you do A, B, but not C, you can maybe not have to do X, but please read the manual in the next version because we will add D and B will probably change, we'll never change A (unless we change our mind)".
By linking with -lm you ensure that your program will work on most reasonable systems for a reasonably foreseeable future. Even though it's not strictly necessary on one particular machine at this particular point in time, with this particular code, compiled with the particular options you had this time.
Because gcc will optimize some of your code. Like printf, gcc can replace fabs calls. To be sure, you can compile your source code with -fno-builtin to forbid gcc from doing so:
yoones#laptop:/tmp/toto$ gcc -fno-builtin main.c
/tmp/cc5fWozq.o: In function `main':
main.c:(.text+0x37): undefined reference to `fabs'
collect2: error: ld returned 1 exit status
You can also use nm to list your executable symbols:
yoones#laptop:/tmp/toto$ nm ./a.out
0000000000600a18 B __bss_start
0000000000600a18 b completed.6661
0000000000600a08 D __data_start
0000000000600a08 W data_start
00000000004004b0 t deregister_tm_clones
0000000000400530 t __do_global_dtors_aux
00000000006007e8 t __do_global_dtors_aux_fini_array_entry
0000000000600a10 D __dso_handle
00000000006007f8 d _DYNAMIC
0000000000600a18 D _edata
0000000000600a20 B _end
0000000000400644 T _fini
0000000000400550 t frame_dummy
00000000006007e0 t __frame_dummy_init_array_entry
00000000004007d8 r __FRAME_END__
00000000006009d0 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000400408 T _init
00000000006007e8 t __init_array_end
00000000006007e0 t __init_array_start
0000000000400650 R _IO_stdin_used
U __isoc99_scanf##GLIBC_2.7
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000006007f0 d __JCR_END__
00000000006007f0 d __JCR_LIST__
w _Jv_RegisterClasses
0000000000400640 T __libc_csu_fini
00000000004005d0 T __libc_csu_init
U __libc_start_main##GLIBC_2.2.5
0000000000400576 T main
U printf##GLIBC_2.2.5
00000000004004f0 t register_tm_clones
0000000000400480 T _start
0000000000600a18 D __TMC_END__
Related
I am currently building in C a complex executable that depends on multiple libraries. The executable and the some of the libraries it uses depend on a specific library, lets call it libXYZ.
I am trying to build the executable with a more recent version of libXYZ, libXYZ.2 while I can not rebuild the other libraries that depend on an older, partially binary incompatible version of libXYZ, libXYZ.1.
I am able to include both .so for libXYZ1 and libXYZ2 in the executable and the code compiles and runs, but when I check the generated executable, some of the chosen symbols for the calls by the executable are for libXYZ1, even if at compile time the headers are for libXYZ2.
Is there a way via linker options to force the executable being built, to always choose libXYZ2 while leaving libXYZ1 available for the other libraries being also linked? I can not rebuild the other libraries that depend on libXYZ, but I can rebuild the executable and libXYZ itself as needed. Thanks.
I'm expanding a bit on one of my comments so the idea is properly formatted and described. This might not be doable in your scenario.
To simplify, we have libx1 which exposes two functions: libx_api and libx1_api. This version of the library is used by libx1_user which exposes a single API: libx1_user which uses both of the libx1 APIs.
We also have libx2 which exposes two functions: libx_api and libx2_api.
We have a program (prog) that depends on libx1_user and libx2.
My suggestion is to wrap libx2 in a dynamic library libx2w which exposes the same APIs as libx2, only with a slight change in name: w_libx_api and w_libx2_api (only the functions that have common names between libx1 and libx2 need this change, but I added the w_ prefix to both functions for consistency).
Now, the code of prog is changed so that every place in which a libx2 version of an API needs to be used it will actually use the wrappers for libx2w. This should be a change that is easy to automate.
Example with code (I will omit the contents of the headers, there's nothing special there, just function prototypes):
libx1.c
#include <stdio.h>
#include "libx1.h"
void libx_api()
{
printf("In libx_api() from libx1\n");
}
void libx1_api()
{
printf("In libx1_api()\n");
}
libx2.c
#include <stdio.h>
#include "libx2.h"
void libx_api()
{
printf("In libx_api() from libx2\n");
}
void libx2_api()
{
printf("In libx2_api()\n");
}
libx1_user.c
#include <stdio.h>
#include "libx1_user.h"
#include "libx1.h"
void libx1_user()
{
printf("Entering libx1_user()\n");
libx_api();
libx1_api();
printf("Exiting libx1_user()\n");
}
libx2_wrapper.c
#include <stdio.h>
#include "libx2wrapper.h"
#include "libx2.h"
void w_libx_api()
{
libx_api();
}
void w_libx2_api()
{
libx2_api();
}
program.c
#include <stdio.h>
#include "libx1_user.h"
#include "libx2wrapper.h"
int main()
{
printf("Using libx1_user()\n");
libx1_user();
printf("Done!\n");
printf("Using libx2 wrappers\n");
w_libx_api(); // this was previously libx_api()
w_libx2_api(); // this was previously libx2_api()
printf("Done!\n");
return 0;
}
Sample CMakeLists.txt for compiling and linking
I'm more familiar with CMake than make so I found it easier to write the corresponding CMakeLists.txt instead of a Makefile.
project(prog)
add_library(x1 STATIC libx1.c)
add_library(x1_user STATIC libx1_user.c)
target_link_libraries(x1_user PRIVATE x1)
add_library(x2 STATIC libx2.c)
add_library(x2w SHARED libx2wrapper.c)
target_link_libraries(x2w PRIVATE x2)
add_executable(prog program.c)
target_link_libraries(prog PRIVATE x2w x1_user)
Running the resulting program
$ ./prog
Using libx1_user()
Entering libx1_user()
In libx_api() from libx1
In libx1_api()
Exiting libx1_user()
Done!
Using libx2 wrappers
In libx_api() from libx1
In libx2_api()
Done!
nm output
$ nm prog
0000000000003d98 d _DYNAMIC
0000000000003fa8 d _GLOBAL_OFFSET_TABLE_
0000000000002000 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
000000000000224c r __FRAME_END__
0000000000002088 r __GNU_EH_FRAME_HDR
0000000000004010 d __TMC_END__
0000000000004010 B __bss_start
w __cxa_finalize##GLIBC_2.2.5
0000000000004000 D __data_start
0000000000001140 t __do_global_dtors_aux
0000000000003d90 d __do_global_dtors_aux_fini_array_entry
0000000000004008 d __dso_handle
0000000000003d88 d __frame_dummy_init_array_entry
w __gmon_start__
0000000000003d90 d __init_array_end
0000000000003d88 d __init_array_start
00000000000012c0 T __libc_csu_fini
0000000000001250 T __libc_csu_init
U __libc_start_main##GLIBC_2.2.5
0000000000004010 D _edata
0000000000004018 B _end
00000000000012c8 t _fini
0000000000001000 t _init
00000000000010a0 T _start
0000000000004010 b completed.8060
0000000000004000 W data_start
00000000000010d0 t deregister_tm_clones
0000000000001180 t frame_dummy
0000000000001234 T libx1_api
00000000000011e6 T libx1_user
000000000000121d T libx_api
0000000000001189 T main
U puts##GLIBC_2.2.5
0000000000001100 t register_tm_clones
U w_libx2_api
U w_libx_api
I found the following post (How to generate gcc debug symbol outside the build target?) on how to split a the compiled file and the debugging symbols.
However, I cannot find any useful information in the debugging file.
For example,
My helloWorld code is:
#include<stdio.h>
int main(void) {
int a;
a = 5;
printf("The memory address of a is: %p\n", (void*) &a);
return 0;
}
I ran gcc -g -o hello hello.c
objcopy --only-keep-debug hello hello.debug
gdb -s main.debug -e main
In gdb, anything I tried won't give me any information on a, I cannot find its address, I cannot find the main function address
For example :
(gdb) info variables
All defined variables:
Non-debugging symbols:
0x0000000000400618 _IO_stdin_used
0x0000000000400710 __FRAME_END__
0x0000000000600e3c __init_array_end
0x0000000000600e3c __init_array_start
0x0000000000600e40 __CTOR_LIST__
0x0000000000600e48 __CTOR_END__
0x0000000000600e50 __DTOR_LIST__
0x0000000000600e58 __DTOR_END__
0x0000000000600e60 __JCR_END__
0x0000000000600e60 __JCR_LIST__
0x0000000000600e68 _DYNAMIC
0x0000000000601000 _GLOBAL_OFFSET_TABLE_
0x0000000000601028 __data_start
0x0000000000601028 data_start
0x0000000000601030 __dso_handle
0x0000000000601038 __bss_start
0x0000000000601038 _edata
0x0000000000601038 completed.6603
0x0000000000601040 dtor_idx.6605
0x0000000000601048 _end
Am I doing something wrong? Am I understanding the debug file incorrectly? Is there even a way to find out an address of compiled variable/function from a saved debugging information?
int a is a stack variable so it does not have a fixed address unless you are in a call to that specific function. Furthermore, each call to that function will allocate its own variable.
When we say "debugging symbols" we usually mean functions and global variables. A local variable is not a "symbol" in this context. In fact, if you compile with optimisations enabled int a would almost certainly be optimised to a register variable so it would not have an address at all, unless you forced it to be written to memory by doing some_function(&a) or similar.
You can find the address of main just by writing print main in GDB. This is because functions are implicitly converted to pointers in C when they appear in value context, and GDB's print uses C semantics.
Thats my code:
int const const_global_init = 2;
int const const_global;
int global_init = 4;
int global;
static int static_global_init = 3;
static int static_global;
static int static_function(){
return 2;
}
double function_with_param(int a){
static int static_local_init = 3;
static int static_local;
return 2.2;
}
int main(){
}
I generate main.o and i try to understood nm output. After i use nm main.o --printfile-name -a i get this output:
main.o:0000000000000000 b .bss
main.o:0000000000000000 n .comment
main.o:0000000000000004 C const_global
main.o:0000000000000000 R const_global_init
main.o:0000000000000000 d .data
main.o:0000000000000000 r .eh_frame
main.o:000000000000000b T function_with_param
main.o:0000000000000004 C global
main.o:0000000000000000 D global_init
main.o:0000000000000027 T main
main.o:0000000000000000 a main.c
main.o:0000000000000000 n .note.GNU-stack
main.o:0000000000000000 r .rodata
main.o:0000000000000000 t static_function
main.o:0000000000000000 b static_global
main.o:0000000000000004 d static_global_init
main.o:0000000000000004 b static_local.1733
main.o:0000000000000008 d static_local_init.1732
main.o:0000000000000000 t .text
I understood 2nd and 3rd column but, i really dont know what is in the first column, whether it is the address or size? I know somethink about .bbs, .comment, .data and .text segments but what is it .eh_frame, .note.GNU-stack and .rodata?
... i really dont know what is in the first column, whether it is the address or size?
My local manpage (from man nm) says
DESCRIPTION
GNU nm lists the symbols from object files objfile.... If no object files are listed as arguments, nm assumes the file a.out.
For each symbol, nm shows:
ยท The symbol value, in the radix selected by options (see below), or hexadecimal by default.
that is, the first column is the 'value' of the symbol. To understand what that means, it's helpful to know something about ELF and the runtime linker, but in general it will simply be an offset into the relevant section.
Understanding something about ELF will also help with the other points: man elf tells us that the .rodata section is read-only data (that is: constant values hardcoded into the program that never change. String literals might go here).
.eh_frame is used for exception-handling and other call-stack-frame metadata (a search for eh_frame has this question as the first hit).
The programming language GAP has a way of compiling into C code using the compiler GAC.
I am trying to test this in the following way, to create a C program from functions written in GAP:
first.g
PrintEO := function() Print("Hello World"); end;
firstGapProg.c
#include <stdio.h>
int main()
{
PrintEO();
return 0;
}
I then run in Bash
$ gac -c first.g
$ ar -cvq libfirstgap.a first.o
$ cc -o gapFirstTest firstGapProg.c libfirstgap.a
This compiles the .g file to a .o, creates library then attempts to link the library and make executable. When I do this I get the error gapProg.c:(.text+0xa): undefined reference to ``G_PrintEO'.
I am guessing this is because I have no template for the function in firstGapProg.c. However I do not actually know how to call the function itself or what it has been saved as in the library?!
When I $nm libfirstgap.a I get the output:
test.o:
U AssGVar
U ChangedBags
U CurrLVars
U CurrStat
0000000000000000 b DefaultName
0000000000000070 b GF_Print
0000000000000078 b G_Print
0000000000000068 b G_PrintEO
U GVarName
0000000000000070 t HdlrFunc1
0000000000000340 t HdlrFunc2
U InitFopyGVar
U InitGlobalBag
U InitHandlerFunc
0000000000000480 t InitKernel
0000000000000200 t InitLibrary
00000000000004f0 T Init__test
0000000000000000 d module
0000000000000050 b NameFunc
0000000000000030 b NamsFunc
0000000000000010 b NargFunc
U NewBag
U NewFunction
U NEW_STRING
0000000000000000 t PostRestore
U PtrBody
U PtrLVars
U UpdateCopyFopyInfo
U YoungBags
Any ideas?
I have written a snippet that has memory problems when dynamically allocating; when compiled with -lefence option, it seems that there is no effect. Here is the code segment:
int main(int argc, char *argv[])
{
int *a = (int *)malloc(2*sizeof(int));
for(int i = 0; i <=2; ++i){
a[i] = i;
printf ("%d\n",a[i]);
}
free(a);
return 0;
}
And the compilation options:
gcc -g3 -Wall -std=c99 outOfBound.c -lefence
The expected result is that when a.out is executed there would be a core dump after i is assigned to 2 and a[i]=i is invoked.
So Why -lefence has no effect?
I have also increased the upper bound in the loop to 9, but there is still no core dump thatelectric-fence invoked. (Actually there is indeed a core dump by default, but this might due to the MALLOC_CHECK_ env virable since when I export MALLOC_CHECK_=0, there would be no more core dump).
UPDATE: the whole result of nm -A a.out is as below:
a.out:08049f28 d _DYNAMIC
a.out:08049ff4 d _GLOBAL_OFFSET_TABLE_
a.out:0804864c R _IO_stdin_used
a.out: w _Jv_RegisterClasses
a.out:08049f18 d __CTOR_END__
a.out:08049f14 d __CTOR_LIST__
a.out:08049f20 d __DTOR_END__
a.out:08049f1c d __DTOR_LIST__
a.out:08048718 r __FRAME_END__
a.out:08049f24 d __JCR_END__
a.out:08049f24 d __JCR_LIST__
a.out:0804a01c A __bss_start
a.out:0804a014 D __data_start
a.out:08048600 t __do_global_ctors_aux
a.out:08048480 t __do_global_dtors_aux
a.out:0804a018 d __dso_handle
a.out: w __gmon_start__
a.out:080485f2 t __i686.get_pc_thunk.bx
a.out:00000000 a __init_array_end
a.out:00000000 a __init_array_start
a.out:080485f0 T __libc_csu_fini
a.out:08048580 T __libc_csu_init
a.out: U __libc_start_main
a.out:0804a01c A _edata
a.out:0804a024 A _end
a.out:0804862c T _fini
a.out:08048648 R _fp_hw
a.out:080483b4 T _init
a.out:08048450 T _start
a.out:0804a01c b completed.6159
a.out:0804a014 W data_start
a.out:0804a020 b dtor_idx.6161
a.out:080484e0 t frame_dummy
a.out: U free
a.out:08048504 T main
a.out: U malloc
a.out: U printf
(I am using a debian package electric-fence on Ubuntu 12.04 32bit, gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3)
Update(20140801):
For electric-fence of version 2.2.4 packaged by debian(testing branch, i.e. jessie), it works.
It is possible you are running into this.
... it must increase the size of the allocation to a multiple of the
word size. In addition, the functions memalign() and valloc() must
honor explicit specifications on the alignment of the memory
allocation, and this, as well can only be implemented by increasing
the size of the allocation. Thus, there will be situations in which
the end of a memory allocation contains some padding space, and
accesses of that padding space will not be detected, even if they are
overruns.
Try exceed the bounds a bit more, and see at what point the overrun detection kicks in.
Once you compile and execute above program without linking it with electric fence library, it may run without any segmentation fault.
So better to link it with electric fence library and then Run it by loading it in gdb giving the following command
$ gdb a.out
....
(gdb)run
Starting program: /home/arif/sysprog-2017/processmgmt/nonlocalgoto/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens <bruce#perens.com>
0
1
Program received signal SIGSEGV, Segmentation fault.
0x000055555555484d in main (argc=1, argv=0x7fffffffe228) at temp.c:8
8 a[i] = i;
So from above output of gdb you can make out the source line number which is causing the problem if you print the value of i at this instant it will be 2 :)