I am trying to use my own printf function so i don't want to include standard include files... so I am compiling my code with -nostdinc
I have created my program something like this:
extern int printf(const char*,...);
printf("Value:%d",1234);
//printf("\n");
It is working fine for this code, but when I use printf("\n") then it is showing undefined reference to 'putchar'.
If i comment printf("\n"); then nm command is showing
$ nm test1.o
U exit
00000000 T main
U printf
00000030 T _start
but if I use printf("\n"); then nm command is showing
$nm test1.o
U exit
00000000 T main
U printf
U putchar
0000003c T _start
I am not getting how and from where putchar is getting included
gcc version 4.8.2 (GCC)
gcc optimizes printf in certain situations. You can look at the function fold_builtin_printf here for the complete details. IIRC, it optimizes calls with one argument followed by a newline to puts/putchar. You can turn it off by specifying -fno-builtin(gcc docs).
Related
I am trying to compile a program so that it starts on a different entry point. I am running WSL1 with Ubuntu 20.04.5, and GCC and G++ 9.4.0
I found that adding the flag -Wl,--entry=foo to the compiler will link foo() as the entry function. Testing, this has worked with gcc, but not with g++.
Using the example file src/main.c:
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("Entering %s:%s\n", __FILE__, __func__);
return 0;
}
int not_main()
{
printf("Entering %s:%s\n", __FILE__, __func__);
exit(0); // Necessary, otherwise it throws a segfault
}
When compiled with gcc -Wl,--entry=not_main -o entry.o src/main.c the output is what I want: Entering src/main.c:not_main.
However, when compiled with g++ -Wl,--entry=not_main -o entry.o src/main.c, the following warning appears: /usr/bin/ld: warning: cannot find entry symbol not_main; defaulting to 0000000000001080.
This defaults to the main() function, outputting Entering src/main.c:main. The function not_main() is not found by the linker, but it is present in the source code.
The documentation for g++ says:
g++ is a program that calls GCC and automatically specifies linking against the C++ library.
I don't see how g++ can differ from gcc, if internally one calls the other. I understand that it is not the compiler but the linker which changes the entry point, and that g++ (unlike gcc) is linking against the C++ library, but I fail to understand how that is problematic.
What am I missing?
Because of name mangling, the function is not not_main but _Z8not_mainv.
how g++ can differ from gcc,
What is the difference between g++ and gcc? why use g++ instead of gcc to compile *.cc files?
C++, unlike C, uses name mangling to distinguish different overloads of the same function name.
When compiled with gcc:
$ objdump -t entry.o | grep not_main
000000000000117c g F .text 0000000000000036 not_main
When compiled with g++:
$ objdump -t entry.o | grep not_main
0000000000000000 *UND* 0000000000000000 not_main
000000000000117c g F .text 0000000000000036 _Z8not_mainv
The *UND*efined reference to not_main was probably placed there by the linker since you requested this as the entry point. The actual not_main function has its name mangled to _Z8not_mainv.
To export not_main under its original name, use extern "C":
extern "C" int not_main()
{
printf("Entering %s:%s\n", __FILE__, __func__);
exit(0); // Necessary, otherwise it throws a segfault
}
I'm trying to use a third party DLL (I'm compiling using MinGW) but I'm facing some troubles. First of all, the DLL exports undecorated names, but the declaration of the functions seen in the header files contain "__stdcall". Appart of that, I'm using C++, but I've sorrounded the include with 'extern "C"'.
The error:
undefined reference to `Play_Stop#4'
I've tried to link directly to the DLL, as G++ is theorically capable of doing that, but I got some "undefined reference"s.
Then I tried to generate a .def file, using gendef (gendef theirDLL.dll) and later I used dlltool to generate an import lib:
dlltool -k --no-leading-underscore -d theirDLL.def -D theirDLL.dll -l theirDLL.a. Note that I used --no-leading-underscore as I observed with nm that all the functions were preceeded by one underscore, which was causing troubles.
However, even doing all of that, I don't get it to link properly. Any ideas?
I've checked that the linker founds the static library.
The function declaration in header file:
BOOL __stdcall Play_Stop(LONG nPort);
The include directive:
extern "C"{
#include "PlaySDK.h"
}
The nm command output (theirDLL.a)
...
daazs00103.o:
00000000 b .bss
00000000 d .data
00000000 i .idata$4
00000000 i .idata$5
00000000 i .idata$6
00000000 i .idata$7
00000000 t .text
00000000 T Play_Stop#4
00000000 I __imp_Play_Stop#4
...
And the error:
undefined reference to `Play_Stop#4'
Thank you in advance!
I am using Cygwin 32-bit under Win7 in a 64-bit machine.
The following program
makefile:
runme: main.cpp asm.o
g++ main.cpp asm.o -o executable
asm.o: asm.asm
nasm -f elf asm.asm -o asm.o
asm.asm:
section .data
section .bss
section .text
global GetValueFromASM
GetValueFromASM:
mov eax, 9
ret
main.cpp:
#include <iostream>
using namespace std;
extern "C" int GetValueFromASM();
int main()
{
cout<<"GetValueFromASM() returned = "<<GetValueFromASM()<<endl;
return 0;
}
is giving me the following error:
$ make
nasm -f elf asm.asm -o asm.o
g++ main.cpp asm.o -o executable
/tmp/cc3F1pPh.o:main.cpp:(.text+0x26): undefined reference to `GetValueFromASM'
collect2: error: ld returned 1 exit status
make: *** [makefile:2: runme] Error 1
I am not understanding why this error is being generated.
How can I get rid of this issue?
You have to prefix your symbols with _, as is customary in Windows/Cygwin:
section .data
section .bss
section .text
global _GetValueFromASM
_GetValueFromASM:
mov eax, 9
ret
The rest of your code should work fine.
An alternative would be to compile with -fno-leading-underscore. However, this may break linking with other (Cygwin system) libraries. I suggest using the first option if portability to other platforms does not matter to you.
Quoting from the GNU Online Docs:
-fleading-underscore
This option and its counterpart, -fno-leading-underscore, forcibly change the way C symbols are represented in the object file. One use is to help link with legacy assembly code.
Warning: the -fleading-underscore switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface. Not all targets provide complete support for this switch.
i have tried to link a programm of mine with the libmodbus opensource lib. After some trouble with automake, i finally managed to compile it.
But now I get a undefined reference error from gcc, when I use one of the functions the library provides in my own programm:
main.cpp:(.text+0x21): undefined reference to `modbus_udp_init(char*, int, __modbus_udp_handle*)'
collect2: Fehler: ld gab 1 als Ende-Status zurück
From my point of view, the arguments of gcc to compile my project are correct:
g++ -v -I ../libmodbus/modbus -o main main.cpp -L../libmodbus/modbus/.libs/ -lmodbus
I checked with nm if the function is really in that library, but everything looks fine for me (I have deleted some parts from the output, to prevent the output from getting too big):
$ nm ../libmodbus/modbus/.libs/libmodbus.a
modbus.o:
0000000000000590 T crc16
U free
U malloc
U memcpy
0000000000000b40 T modbus_diagnostics
0000000000000d90 T modbus_error_get_exception_code
0000000000000100 C modbus_error_str
0000000000000cf0 T modbus_exception
[...]
modbus-udp.o:
U bcopy
U close
U __errno_location
U gethostbyname
U modbus_error_str
U modbus_tcp_frame_pack
U modbus_tcp_frame_parse
0000000000000000 T modbus_udp_close
0000000000000030 T modbus_udp_init
0000000000000220 T modbus_udp_recv
0000000000000190 T modbus_udp_send
0000000000000010 r __PRETTY_FUNCTION__.4582
0000000000000000 r __PRETTY_FUNCTION__.4592
U recvfrom
U sendto
U setsockopt
U snprintf
U socket
U strerror
modbus-tcp.o:
[...]
modbus-serial.o:
[...]
Does someone have an idea why gcc can't resolve the symbol?
As noloader suggested, i missed adding extern "C" as libmodbus is a C-library. I edited my source:
extern "C" {
#include <modbus.h>
#include <modbus-udp.h>
}
Now it compiles fine. Thank you!
I'm trying to add global constructor support on an embedded target (ARM Cortex-M3).
Lets say I've the following code:
class foobar
{
int i;
public:
foobar()
{
i = 100;
}
void inc()
{
i++;
}
};
foobar foo;
int main()
{
foo.inc();
for (;;);
}
I compile it like this:
arm-none-eabi-g++ -O0 -gdwarf-2 -mcpu=cortex-m3 -mthumb -c foo.cpp -o foo.o
When I look at the .init_array section with objdump it shows the .init_section has a zero size.
I do get an symbol named _Z41__static_initialization_and_destruction_0ii.
When I disassemble the object file I see that the global construction is done in the static_initialization_and_destruction symbol.
Why isn't a pointer added to this symbol in the .init_section?
I know it has been almost two years since this question was asked, but I just had to figure out the mechanics of bare-metal C++ initialization with GCC myself, so I thought I'd share the details here. There turns out to be a lot of out-of-date or confusing information on the web. For example, the oft-mentioned collect2 wrapper does not appear to be used for ARM ELF targets, since its arbitrary section support enables the approach described below.
First, when I compile the code above with the given command line using Sourcery CodeBench Lite 2012.09-63, I do see the correct .init_array section size of 4:
$ arm-none-eabi-objdump -h foo.o
foo.o: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
...
13 .init_array 00000004 00000000 00000000 0000010c 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
...
When I look at the section contents, it just contains 0:
$ arm-none-eabi-objdump -j .init_array -s foo.o
Contents of section .init_array:
0000 00000000 ....
However, there is also a relocation section that sets it correctly to _GLOBAL__sub_I_foo:
$ arm-none-eabi-objdump -x foo.o
...
RELOCATION RECORDS FOR [.init_array]:
OFFSET TYPE VALUE
00000000 R_ARM_TARGET1 _GLOBAL__sub_I_foo
In general, .init_array points to all of your _GLOBAL__sub_I_XXX initializer stubs, each of which calls its own copy of _Z41__static_initialization_and_destruction_0ii (yes, it is multiply-defined), which calls the constructor with the appropriate arguments.
Because I'm using -nostdlib in my build, I can't use CodeSourcery's __libc_init_array to execute the .init_array for me, so I need to call the static initializers myself:
extern "C"
{
extern void (**__init_array_start)();
extern void (**__init_array_end)();
inline void static_init()
{
for (void (**p)() = __init_array_start; p < __init_array_end; ++p)
(*p)();
}
}
__init_array_start and __init_array_end are defined by the linker script:
. = ALIGN(4);
.init_array :
{
__init_array_start = .;
KEEP (*(.init_array*))
__init_array_end = .;
}
This approach seems to work with both the CodeSourcery cross-compiler and native ARM GCC, e.g. in Ubuntu 12.10 for ARM. Supporting both compilers is one reason for using -nostdlib and not relying on the CodeSourcery CS3 bare-metal support.
Timmmm,
I just had the same issue on the nRF51822 and solved it by adding KEEP() around a couple lines in the stock Nordic .ld file:
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
While at it, I did the same to the fini_array area too. Solved my problem and the linker can still remove other unused sections...
You have only produced an object file, due to the -c argument to gcc. To create the .init section, I believe that you need to link that .o into an actual executable or shared library. Try removing the -c argument and renaming the output file to "foo", and then check the resulting executable with the disassembler.
If you look carefully _Z41__static_initialization_and_destruction_0ii would be called inside global constructor. Which inturn would be linked in .init_array section (in arm-none-eabi- from CodeSourcery.) or some other function (__main() if you are using Linux g++). () This should be called at startup or at main().
See also this link.
I had a similar issue where my constructors were not being called (nRF51822 Cortex-M0 with GCC). The problem turned out to be due to this linker flag:
-Wl,--gc-sections
Don't ask me why! I thought it only removed dead code.