EmbDev.net

Forum: ARM programming with GCC/GNU tools libc overrides own printf-function


von Daniel Jerolm (Guest)


Rate this post
useful
not useful
Hello,

I'm using a Philips LPC2138 (with Olimex Header board) for my actual
project, a control panel for light shows (DMX 512, dimmers, scanners,
moving-heads, strobes, sound-to-light and all these stuff). I've already
a lot of experience with C, C++, 8051 and windows programming (dotNET).
It's my first project using an ARM processor and WINARM from Martin
Thomas, so please don't be cruel to me :-)

I don't really want to use any librarys like Newlib, libc etc. since
limited resources. (OK, 512K of flash seems to be a lot, but the control
panel is also going to be a really huge thing...)

So I wrote my own graphic lcd support, my own low-level filesystem for
storing files and directorys into an external I2C-eeprom and a
printf-function.

Problem is that the linker is using printf from libc.a instead of my own
function even though there is no include for this lib nor in any of my
c-files neither in the makefile.

Is it possible that this lib is somehow automatically included?

A workaround to fix this would be to rename my own printf to myprintf or
something, but I prefer printf...

Thanks and best regards

Daniel Jerolm

(for eMails please remove the no-spam)

von Clifford S. (clifford)


Rate this post
useful
not useful
It is not an issue of header files, they are processed by the compiler.
It is an issue of the linker resolving symbols and where it finds them.
I believe that if it matches a symbol in an object file it overrides any
math subsequently found in the library (because it will not even be
looking), so it seems that you have not linked the object file
containing your printf. Alternatively if you are using C++ you have a
C/C++ linkage issue and it is not matching against your C++ compiled
printf().

It is a good idea in these circumstances to post your build log (the
text output of your make/build).

If invoking the linker via the compiler you can specify -nostdlib or
-nodefaultlibs (if using the linker directly you have to specify the
libraries and startup files explicitly in any case) - if you choose to
use these options, you must supply your own support for calls that the
compiler may generate internally (see
http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Link-Options.html#Link-Options
for details). If you have the -lc option you are linking libc.a
regardless of the options mentioned above. Outside of stdio, and the C++
standard library, most standard library functions are trivial and highly
optimised - you'd do well to retain their services, and ripping out the
library will cause problems for the compiler. Without the standard
library you will loose runtime support for dynamic memory allocation
(malloc, new etc.), and the memory manipulation routines that the
compiler generates calls to internally for static initialisation for
example.

I would suggest that you only call your function printf() is it behaves
exactly like printf() - i.e. uses format specifiers and is variadic -
omitting support for floating point perhaps may be reasonable. The
reason being that if your code is later maintained by someone else, they
may attempt to use features your version does not support and waste time
trying to debug it. So it is best to highlight the fact that it is not
ISO compliant and is hardware specific by using an alternative name;
lcd_printf() for example (myprintf is not really a good name!)

In all I believe that an attempt to omit the standard library will cause
mre problems than it is worth. Nonetheless what you have described
should work, so if you still whant to make it work, post the build log
so we can see what you are really doing (make it a log from a clean
build).

Clifford

von Daniel Jerolm (Guest)


Rate this post
useful
not useful
Thanks for your answer.

You are right, kicking out the libs completly will cause some problems,
so I'll have to rename my function or make friends with newlib. Today I
spend some time thinking about this and I came to the conclusion that
it's the best to make friends with newlib.

Nevertheless here is my build log. As you can see I've still the
switches -lnewlib-lpc, -lm, -lc and -lgcc turned on. I tryed to remove
them but it didn't change anythink, but applying -nodefaultlibs (as you
mentioned in your answer) causes a lot of trouble. If I call my own
printf something else like lcd_printf code works fine and I don't get
the "undefined references ..."-errors shown below.

If I don't get it working it's not a dramatic problem, then I'll provide
the "undefined references" in my programm and the newlib printf should
work.

------- begin --------
arm-elf-gcc (GCC) 4.1.1 (WinARM)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.


Assembling (ARM-only): StartUp.S
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -x assembler-with-cpp -DROM_RUN
-Wa,-adhlns=StartUp.lst,-gdwarf-2 StartUp.S -o StartUp.o

Compiling C (ARM-only): timing.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=timing.lst
-MD -MP -MF .dep/timing.o.d -Wstrict-prototypes -Wmissing-declarations
-Wmissing-prototypes -Wnested-externs  -std=gnu99 timing.c -o timing.o

Compiling C (ARM-only): codeblinker.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused
-Wa,-adhlns=codeblinker.lst   -MD -MP -MF .dep/codeblinker.o.d
-Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes
-Wnested-externs  -std=gnu99 codeblinker.c -o codeblinker.o

Compiling C (ARM-only): printf.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=printf.lst
-MD -MP -MF .dep/printf.o.d -Wstrict-prototypes -Wmissing-declarations
-Wmissing-prototypes -Wnested-externs  -std=gnu99 printf.c -o printf.o

Compiling C (ARM-only): VIC.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=VIC.lst
-MD -MP -MF .dep/VIC.o.d -Wstrict-prototypes -Wmissing-declarations
-Wmissing-prototypes -Wnested-externs  -std=gnu99 VIC.c -o VIC.o

Compiling C (ARM-only): timer.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=timer.lst
-MD -MP -MF .dep/timer.o.d -Wstrict-prototypes -Wmissing-declarations
-Wmissing-prototypes -Wnested-externs  -std=gnu99 timer.c -o timer.o

Compiling C (ARM-only): HID.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=HID.lst
-MD -MP -MF .dep/HID.o.d -Wstrict-prototypes -Wmissing-declarations
-Wmissing-prototypes -Wnested-externs  -std=gnu99 HID.c -o HID.o

Compiling C (ARM-only): Display.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused
-Wa,-adhlns=Display.lst   -MD -MP -MF .dep/Display.o.d
-Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes
-Wnested-externs  -std=gnu99 Display.c -o Display.o

Compiling C (ARM-only): main.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=main.lst
-MD -MP -MF .dep/main.o.d -Wstrict-prototypes -Wmissing-declarations
-Wmissing-prototypes -Wnested-externs  -std=gnu99 main.c -o main.o
main.c: In function 'main':
main.c:198: warning: declaration of 'i' shadows a previous local
main.c:49: warning: shadowed declaration is here

Linking: main.elf
arm-elf-gcc  -mcpu=arm7tdmi  -I. -gdwarf-2 -DROM_RUN  -O0 -Wall
-Wcast-align -Wcast-qual -Wimplicit  -Wpointer-arith -Wswitch
-Wredundant-decls -Wreturn-type -Wshadow -Wunused
-Wa,-adhlns=StartUp.lst   -MD -MP -MF .dep/main.elf.d StartUp.o
timing.o codeblinker.o printf.o VIC.o timer.o HID.o Display.o main.o
--output main.elf -nostartfiles -Wl,-Map=main.map,--cref -lnewlib-lpc
-lm -lc -lgcc -Tbuild/LPC2138-ROM.ld
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(fr 
eer.o):
In function `_malloc_trim_r':
mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x64): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x84): undefined reference to `_sbrk_r'
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(ma 
kebuf.o):
In function `__smakebuf':
makebuf.c:(.text+0x3c): undefined reference to `_fstat_r'
makebuf.c:(.text+0x110): undefined reference to `isatty'
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(ma 
llocr.o):
In function `_malloc_r':
mallocr.c:(.text+0x424): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r'
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(st 
dio.o):
In function `__sclose':
stdio.c:(.text+0xc): undefined reference to `_close_r'
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(st 
dio.o):
In function `__sseek':
stdio.c:(.text+0x30): undefined reference to `_lseek_r'
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(st 
dio.o):
In function `__swrite':
stdio.c:(.text+0x84): undefined reference to `_lseek_r'
stdio.c:(.text+0xac): undefined reference to `_write_r'
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(st 
dio.o):
In function `__sread':
stdio.c:(.text+0xd0): undefined reference to `_read_r'
collect2: ld returned 1 exit status
make.exe: *** [main.elf] Error 1

> Process Exit Code: 2
> Time Taken: 00:02

Daniel

von Daniel Jerolm (Guest)


Rate this post
useful
not useful
I'm using iprintf from the newlib now. Problem solved, but payed with
about 25KB flash memory...

von Clifford S. (clifford)


Rate this post
useful
not useful
Daniel Jerolm wrote:
> If I don't get it working it's not a dramatic problem, then I'll provide
> the "undefined references" in my programm and the newlib printf should
> work.
Yes you need to provide Newlib's syscalls. In most cases thay can simply
be stubs - especially if you are not using stdio. The sbrk call should
be implemented however,  unless you are certain never to use dynamic
memory allocation or anything that utilises the heap. Example
implementations are provided with WinARM, although that is what I
thought newlib-lpc provided (note that this library is not Newlib
itself, Newlib is the collective name for libm and libc provided with
WinARM).

You can safely remove libm if you are not using the C math routines -
and without a hardware FPU you may be advised not to for some
applications. libgcc should be kept however, it contains compiler
support routines. However if you never make the calls, the code will not
of course be included in the build, so probably best to leave them.

> I'm using iprintf from the newlib now. Problem solved, but payed with
> about 25KB flash memory...
Much of that code however is probably shared by other routines, so using
sprintf() for example would have negligable additional overhead. Note
that printf() also has a significant runtime stack requirement.
Personally I'd do whatever is easiest right now and worry about the
application size when it starts to become a problem, which it may never
do so.


Clifford

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.