Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Thread

Linker Problems

Linker Problems

2005-12-19 by miruffer

Hi,

I have big problems with the gcc-linker. Last week I compiled the
newest version of gcc(4.0.2), binutils(2.16.1) and newlib(1.13) under
linux debian. Before I worked with WinARM(gcc 4.0.0).

I tried to compile my project with the new toolchain. No warnings no
errors. But the printf didn't work. To let the printf work via uart1 I
have initialized it and have rewritten some function of the libc:
_write_r and _read_r. Everything works well with WinARM. Now I looked
in the assembler code compiled with the new toolchain and the linker
has used the _write_r from libc and not my new one.

Can I force the linker to use my new one?

thanks, miru

Re: [lpc2000] Linker Problems

2005-12-19 by Tom Walsh

miruffer wrote:

>Hi,
>
>I have big problems with the gcc-linker. Last week I compiled the
>newest version of gcc(4.0.2), binutils(2.16.1) and newlib(1.13) under
>linux debian. Before I worked with WinARM(gcc 4.0.0).
>
>I tried to compile my project with the new toolchain. No warnings no
>errors. But the printf didn't work. To let the printf work via uart1 I
>have initialized it and have rewritten some function of the libc:
>_write_r and _read_r. Everything works well with WinARM. Now I looked
>in the assembler code compiled with the new toolchain and the linker
>has used the _write_r from libc and not my new one.
>
>Can I force the linker to use my new one?
>
>  
>
Sure, get a large hammer...  I would look to your library itself, you 
have to turn on some options within newlib to compile it out into stubs 
for some of the I/O code.  Take a look at the scripts I use to build my 
development environment with, I use the newlib stubs to do char I/O from 
the library: 


http://www.openhardware.net/?title=ARM%20Thumb%20tools%20for%20LPC2000&dir=ArmTools&file=ThumbToolchain.html

Regards,

TomW

-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Re: Linker Problems

2005-12-21 by miruffer

Hi,

thank you for your answer. I look at your scripts and have seen that
you use the flag --disable-newlib-supplied-syscalls. I have rebuilt my
GNU Toolchain. 
When the linker links my project, there are the errors shown below.

/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(writer.o):
In function `_write_r':
../../../../../newlib-1.13.0/newlib/libc/reent/writer.c:58: undefined
reference to `_write'
/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(closer.o):
In function `_close_r':
../../../../../newlib-1.13.0/newlib/libc/reent/closer.c:53: undefined
reference to `_close'
/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(fstatr.o):
In function `_fstat_r':
../../../../../newlib-1.13.0/newlib/libc/reent/fstatr.c:62: undefined
reference to `_fstat'
/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(lseekr.o):
In function `_lseek_r':
../../../../../newlib-1.13.0/newlib/libc/reent/lseekr.c:58: undefined
reference to `_lseek'
/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(readr.o):
In function `_read_r':
../../../../../newlib-1.13.0/newlib/libc/reent/readr.c:58: undefined
reference to `_read'
/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libstdc++.a(eh_personality.o):



All the functions he can't find, are exsisting in my own libary the
linker had opend before. I can't understand that.


thanks miru

In function `base_of_encoded_value':
--- In lpc2000@yahoogroups.com, Tom Walsh <tom@o...> wrote:
>
> miruffer wrote:
> 
> >Hi,
> >
> >I have big problems with the gcc-linker. Last week I compiled the
> >newest version of gcc(4.0.2), binutils(2.16.1) and newlib(1.13) under
> >linux debian. Before I worked with WinARM(gcc 4.0.0).
> >
> >I tried to compile my project with the new toolchain. No warnings no
> >errors. But the printf didn't work. To let the printf work via uart1 I
> >have initialized it and have rewritten some function of the libc:
> >_write_r and _read_r. Everything works well with WinARM. Now I looked
> >in the assembler code compiled with the new toolchain and the linker
> >has used the _write_r from libc and not my new one.
> >
> >Can I force the linker to use my new one?
> >
> >  
> >
> Sure, get a large hammer...  I would look to your library itself, you 
> have to turn on some options within newlib to compile it out into stubs 
> for some of the I/O code.  Take a look at the scripts I use to build my 
> development environment with, I use the newlib stubs to do char I/O
from 
> the library: 
> 
> 
>
http://www.openhardware.net/?title=ARM%20Thumb%20tools%20for%20LPC2000&dir=ArmTools&file=ThumbToolchain.html
Show quoted textHide quoted text
> 
> Regards,
> 
> TomW
> 
> -- 
> Tom Walsh - WN3L - Embedded Systems Consultant
> http://openhardware.net, http://cyberiansoftware.com
> "Windows? No thanks, I have work to do..."
> ----------------------------------------------------
>

Re: [lpc2000] Re: Linker Problems

2005-12-21 by Tom Walsh

miruffer wrote:

>Hi,
>
>thank you for your answer. I look at your scripts and have seen that
>you use the flag --disable-newlib-supplied-syscalls. I have rebuilt my
>GNU Toolchain. 
>When the linker links my project, there are the errors shown below.
>
>  
>

Absolutely correct.  You've done it the right way.  Now, if you want to 
know what can be done with those missing routines, also get a copy of 
the RDCF2 filesystem source (also from my site).  *You* provide those 
functions: write_r, open_r, etc..


>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(writer.o):
>In function `_write_r':
>../../../../../newlib-1.13.0/newlib/libc/reent/writer.c:58: undefined
>reference to `_write'
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(closer.o):
>In function `_close_r':
>../../../../../newlib-1.13.0/newlib/libc/reent/closer.c:53: undefined
>reference to `_close'
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(fstatr.o):
>In function `_fstat_r':
>../../../../../newlib-1.13.0/newlib/libc/reent/fstatr.c:62: undefined
>reference to `_fstat'
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(lseekr.o):
>In function `_lseek_r':
>../../../../../newlib-1.13.0/newlib/libc/reent/lseekr.c:58: undefined
>reference to `_lseek'
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(readr.o):
>In function `_read_r':
>../../../../../newlib-1.13.0/newlib/libc/reent/readr.c:58: undefined
>reference to `_read'
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libstdc++.a(eh_personality.o):
>
>
>
>All the functions he can't find, are exsisting in my own libary the
>linker had opend before. I can't understand that.
>
>
>  
>
When you compile newlib, without the stubs, it assumes that it will be 
dealing with an operating system which would provide a call entry 
structure to perform device I/O.   Since you are not using an operating 
system, such as Linux, you have to provide that last bit of code to 
bridge between the library (abstraction) and your hardware (reality).

The newlib, nor any library, is intended to provide a "final solution".  
They cannot, hardware varies from environ to environ.  It is up to you, 
ultimately, to see that the "operating system" provide a means to move 
the data stream coming out of the library over to the hardware.  With 
something like Linux, we do this be means of the various hardware driver 
code and the SysCalls.  When you don't have an operating system, the 
same requirement still exists to physically connect the data stream from 
the library to the hardware.

This is what the RDCF2 code is about.  It illustrates how to do device 
(hardware) interfacing to newlib, so that you can use filestreams such 
as: fopen(), fread(), fwrite(), fgetc(), etc..  I only provided code to 
interface to an SD drive.  The application that I'm building does not 
require, nor tolerate, file streams to the serial port(s).  Having said 
that, you can add a device "UARTx" to the device table, then add another 
file identical in structure to that of 'mmc_module.c'.  Take a look at 
that file, at the bottom is the DEVICE_TABLE_ENTRY struct which provides 
the entry points to get work done.  This is the "final link" between 
newlib and the hardware.  The write_r, read_r, open_r code I provide is 
the mechanism to handle multiple data streams and to direct those 
streams to the various hardware.

I had taken a general purpose approach to implementing the stub code.  
There are two key elements of the interfacing process: adding a new 
device to the DeviceTable array, adding a new module which contains the 
implementation of the device entry.  The code in between, all those 
ending in "*_r.c" do not need to be altered.

1. devices.c contains the device table.
2. sysdefs.h contains the device IDs.
3. mmc_module.c illustrates the implementation of the device.

You simply add your new module code and make an entry into the device table.

I see that this may be confusing to a first time user of libraries on 
embedded systems.  All embedded system libraries function in essentially 
the same manner.  Ultimately, there has to be "bridging code" written by 
the end-user to provide a link between the hardware and the library.

While you could get deep inside the guts of newlib and hack your way 
into getting the write() function to give you an output you desire, I 
would advise against it.


TomW



-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Re: [lpc2000] Re: Linker Problems

2005-12-21 by Tom Walsh

miruffer wrote:

>Hi,
>
>thank you for your answer. I look at your scripts and have seen that
>you use the flag --disable-newlib-supplied-syscalls. I have rebuilt my
>GNU Toolchain. 
>When the linker links my project, there are the errors shown below.
>
>  
>
This may explain a bit better how newlib stubs operate:

http://www.openhardware.net/?title=Newlib%20stub%20interface&dir=rdcf2&file=newlibstubs.html

TomW


-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Re: Linker Problems

2005-12-21 by miruffer

Hi,

thank you very much for your explanation and the provided source code,
but I think you misunderstood me. I have written the routines _write_r
and _read_r and so on. I compiled these new written functions and
build my own small library called libosarm.a . If I disassemble this
library there is the correct assembler code inside. But if I link my
project with arm-elf-gcc $FLAGS -o tst *.o -Wl,-verbose -losarm I can
see that the linker opens my library, but after that he opens libc.a
and shows the errors.

regards, miru

--- In lpc2000@yahoogroups.com, Tom Walsh <tom@o...> wrote:
>
> miruffer wrote:
> 
> >Hi,
> >
> >thank you for your answer. I look at your scripts and have seen that
> >you use the flag --disable-newlib-supplied-syscalls. I have rebuilt my
> >GNU Toolchain. 
> >When the linker links my project, there are the errors shown below.
> >
> >  
> >
> 
> Absolutely correct.  You've done it the right way.  Now, if you want to 
> know what can be done with those missing routines, also get a copy of 
> the RDCF2 filesystem source (also from my site).  *You* provide those 
> functions: write_r, open_r, etc..
> 
> 
>
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(writer.o):
> >In function `_write_r':
> >../../../../../newlib-1.13.0/newlib/libc/reent/writer.c:58: undefined
> >reference to `_write'
>
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(closer.o):
> >In function `_close_r':
> >../../../../../newlib-1.13.0/newlib/libc/reent/closer.c:53: undefined
> >reference to `_close'
>
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(fstatr.o):
> >In function `_fstat_r':
> >../../../../../newlib-1.13.0/newlib/libc/reent/fstatr.c:62: undefined
> >reference to `_fstat'
>
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(lseekr.o):
> >In function `_lseek_r':
> >../../../../../newlib-1.13.0/newlib/libc/reent/lseekr.c:58: undefined
> >reference to `_lseek'
>
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libc.a(readr.o):
> >In function `_read_r':
> >../../../../../newlib-1.13.0/newlib/libc/reent/readr.c:58: undefined
> >reference to `_read'
>
>/opt/arm-tools/lib/gcc/arm-elf/4.0.2/../../../../arm-elf/lib/libstdc++.a(eh_personality.o):
> >
> >
> >
> >All the functions he can't find, are exsisting in my own libary the
> >linker had opend before. I can't understand that.
> >
> >
> >  
> >
> When you compile newlib, without the stubs, it assumes that it will be 
> dealing with an operating system which would provide a call entry 
> structure to perform device I/O.   Since you are not using an operating 
> system, such as Linux, you have to provide that last bit of code to 
> bridge between the library (abstraction) and your hardware (reality).
> 
> The newlib, nor any library, is intended to provide a "final
solution".  
> They cannot, hardware varies from environ to environ.  It is up to you, 
> ultimately, to see that the "operating system" provide a means to move 
> the data stream coming out of the library over to the hardware.  With 
> something like Linux, we do this be means of the various hardware
driver 
> code and the SysCalls.  When you don't have an operating system, the 
> same requirement still exists to physically connect the data stream
from 
> the library to the hardware.
> 
> This is what the RDCF2 code is about.  It illustrates how to do device 
> (hardware) interfacing to newlib, so that you can use filestreams such 
> as: fopen(), fread(), fwrite(), fgetc(), etc..  I only provided code to 
> interface to an SD drive.  The application that I'm building does not 
> require, nor tolerate, file streams to the serial port(s).  Having said 
> that, you can add a device "UARTx" to the device table, then add
another 
> file identical in structure to that of 'mmc_module.c'.  Take a look at 
> that file, at the bottom is the DEVICE_TABLE_ENTRY struct which
provides 
> the entry points to get work done.  This is the "final link" between 
> newlib and the hardware.  The write_r, read_r, open_r code I provide is 
> the mechanism to handle multiple data streams and to direct those 
> streams to the various hardware.
> 
> I had taken a general purpose approach to implementing the stub code.  
> There are two key elements of the interfacing process: adding a new 
> device to the DeviceTable array, adding a new module which contains the 
> implementation of the device entry.  The code in between, all those 
> ending in "*_r.c" do not need to be altered.
> 
> 1. devices.c contains the device table.
> 2. sysdefs.h contains the device IDs.
> 3. mmc_module.c illustrates the implementation of the device.
> 
> You simply add your new module code and make an entry into the
device table.
> 
> I see that this may be confusing to a first time user of libraries on 
> embedded systems.  All embedded system libraries function in
essentially 
> the same manner.  Ultimately, there has to be "bridging code"
written by 
Show quoted textHide quoted text
> the end-user to provide a link between the hardware and the library.
> 
> While you could get deep inside the guts of newlib and hack your way 
> into getting the write() function to give you an output you desire, I 
> would advise against it.
> 
> 
> TomW
> 
> 
> 
> -- 
> Tom Walsh - WN3L - Embedded Systems Consultant
> http://openhardware.net, http://cyberiansoftware.com
> "Windows? No thanks, I have work to do..."
> ----------------------------------------------------
>

Re: Linker Problems

2005-12-21 by rtstofer

> This may explain a bit better how newlib stubs operate:
> 
> http://www.openhardware.net/?title=Newlib%20stub%
20interface&dir=rdcf2&file=newlibstubs.html
> 
> TomW

Tom,

Great explanation!

Richard

Re: [lpc2000] Re: Linker Problems

2005-12-21 by Tom Walsh

miruffer wrote:

>Hi,
>
>thank you very much for your explanation and the provided source code,
>but I think you misunderstood me. I have written the routines _write_r
>and _read_r and so on. I compiled these new written functions and
>build my own small library called libosarm.a . If I disassemble this
>library there is the correct assembler code inside. But if I link my
>project with arm-elf-gcc $FLAGS -o tst *.o -Wl,-verbose -losarm I can
>see that the linker opens my library, but after that he opens libc.a
>and shows the errors.
>
>  
>

Then try this:

arm-elf-gcc $FLAGS -o tst *.o -Wl,-verbose -lc -losarm


Tell it to link in libc, then libosarm.  It should then link in libc, 
then look to subsequent libraries to resolve the missing references for 
libc.  The linker works from left to right, symbols unresolved at that 
point, are found only in subsequent libraries, not in the the previous 
ones.  I have abandoned the use of code archives in my project because 
the linking order got too wacky:

INPUT( -lc -lsystem -lc -liface -lc -lmmc -lc -luarts -liface -lc -lstdc 
-lgcc );

At that point, I felt there must be a better way! :(   There was, 
eliminate all those stupid archives.  But, then I was faced with the 
problem of how to build a list of object modules to link together.  This 
is my project tree:

EvntCPU/
|-- facp
|   |-- datatest
|   `-- include
|-- iface
|   `-- include
|-- include
|-- mmc
|   `-- include
|-- setup
|   |-- include
|   `-- menuSrc
|-- system
|   `-- include
|-- uarts
|   `-- include
`-- upgrade

There are 73 object files that need to be link, these mostly in the 
child directories off the project root.  What I needed to do was have 
something that told gcc to link all the object files.  But the only way 
I could think to do this was to give a list of all of them, complete 
with path/object.o references.  The solution to that is in the Makefiles.

================== project Makefile ===================
export LINKOBJS=.linkobjs

MODULE_DIRS = setup iface system facp mmc uarts

# Default target.
all: announce buildModules build

announce:
   @echo "** Building EVNT(2138)"

buildModules:
   @rm -f $(LINKOBJS)
   @for subdir in $(MODULE_DIRS) ; do \
      $(MAKE) -C $$subdir ; \
   done

build: elf bin lss sym

=============== end ===================

As each of the MODULE_DIRS are built, the append a list of object files 
into the main list.  This file is then used when linking.  Here is how I 
create that list of objects within each MODULE_DIRS:


========== subdir Makefile ======================

ifndef $(PROJSUBDIR)
PROJSUBDIR=$(shell /bin/pwd)/../
endif

CURSUBDIR=$(shell /bin/pwd | sed 's:/.*/::')
DEPEND=$(PROJSUBDIR)/.depend

SRCS := $(wildcard *.c)
OBJS := $(patsubst %.c,%.o,$(SRCS))
LOBJS := $(patsubst %.c,$(CURSUBDIR)/%.o,$(SRCS))


all: announce $(OBJS) finish

finish:
   echo -n "$(LOBJS) " >> ../$(LINKOBJS)

announce:
   @echo "   Building iface"

%.o: %.c
   $(CC) $(EXTRAINCS) $(THUMB) $(THUMB_IW) $(OPTNONE) $(ALL_CFLAGS) -c 
$< -o $@
   touch $(DEPEND)

=========== end ========================

LOBJS is the key.  When the finish rule is run, it appends to the main 
list all the object files with the current dir.  This occurs  for each 
and every MODULE_DIRS dir.  Ultimately, back at the main project 
Makefile we link everything to make the elf file:

==============  project Makefile =====================

%.elf: $(OBJ) $(DEPEND)
   $(CC) $(OPTNONE) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS) `cat 
$(LINKOBJS)`


=============== end =======================

Note the backticks surrounding the cat $(LINKOBJS), effectively the 
contents of the file containing all those object filenames we collected 
appear there.   Also notice the $(DEPEND), that is used as a build flag 
file.  When a subdir compiles a new object file, it touches (dates + 
time) the depend file.  Later, the depend file is used within the ELF 
rule to see if linking is required (build a new elf image).

If you haven't mastered the Makefiles yet, do so.  It does take some 
work to get them to make sense, but the ability to create / manipulate 
your own make system is well worth the effort!  Especially if you plan 
on continuing to do more than blink an LED.  ;-)

We don't need no stinkin' archives!


TomW



-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Re: [lpc2000] Re: Linker Problems

2005-12-21 by Tom Walsh

rtstofer wrote:

>>This may explain a bit better how newlib stubs operate:
>>
>>http://www.openhardware.net/?title=Newlib%20stub%
>>    
>>
>20interface&dir=rdcf2&file=newlibstubs.html
>  
>
>>TomW
>>    
>>
>
>Tom,
>
>Great explanation!
>
>Richard
>
>  
>
Thanks Richard.  Knowledge is free.  I don't mind sharing knowledge as 
most people don't know what it is that I'm talking about anyway, heh.  ;-)

TomW


>
>
>
>
>
>
> 
>Yahoo! Groups Links
>
>
>
> 
>
>
>  
>


-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.