EmbDev.net

Forum: ARM programming with GCC/GNU tools YAGARTO newlib, undefined reference _sbrk


von Staffan B. (staffan_b)


Rate this post
useful
not useful
Hello,

To make a long story short I have switched from the Yagarto package with 
arm-elf (old, but good, Olimex GCCFD) to a fairly recent version using 
arm-none-eabi (updating the IDE based on the Yagarto homepage this time 
--- many thanks to Michael Fischer for putting it all together!).
When I compile my project I get the following error message (quite a few 
object files removed from the link line for clarity):


arm-none-eabi-ld -v -Lc:\Programs\Yagarto\lib\gcc\arm-none-eabi\4.6.2 
-Lc:\Programs\Yagarto\arm-none-eabi\lib -L. -Map main.map 
-T2138_demo.cmd  -o main.out  crt.o main.o adcAD7686.o timer.o 
UARTStdIO.o --start-group -lm -lg -lgcc -lc --end-group
GNU ld (GNU Binutils) 2.21
c:\Programs\Yagarto\arm-none-eabi\lib\libg.a(lib_a-sbrkr.o): In function 
`_sbrk_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/.. 
/../../../../newlib-1.19.0/newlib/libc/reent/sbrkr.c:60:  undefined 
reference to `_sbrk'
make: *** [main.out] Error 1

**** Build Finished ****


It seems like there is a reference to the function _sbrk. Apparently 
some function is calling this that I'm unaware of. Looking on the net, 
it seems like _sbrk is a very hardware dependent function, but I can't 
find any library (newlib?) for my LPC2138 and I'm not experienced enough 
to write it myself. I tried making a simple stub and making a super 
simple libnewlib.a only including this stub. Turns out the linking works 
out, but the controller hangs...


The same line based on arm-elf works and can run the code so my guess is 
that I - for some reason - need the newlib and the _sbrk function. Or 
rather, using arm-none-eabi I use some function that makes a call to 
_sbrk.

Any suggestions for the following would be highly appreciated:

1. Is there any way to find out what function actually is calling _sbrk? 
When stepping through the controller code, it hangs when returning from 
a function call so it's not obvious there.
2. Where can I find information about the difference between elf and 
none-eabi (what is it? - OK, consider me newbie)?
3. Can anyone suggest a working newlib (with _sbrk) for the LPC2138? The 
Yagarto that I have states newlib 1.19, but when I look through the 
package, I only find a newlib.h file?

Many thanks in advance!

Regards,
    Staffan

von Oliver (Guest)


Rate this post
useful
not useful
Use this as a starting point:

http://www.yagarto.de/download/yagarto/syscalls.c


Oliver

von Staffan B. (staffan_b)


Rate this post
useful
not useful
Hello,

Many thanks. I find a _sbrk_r, but no _sbrk? The stub I created earlier 
looks like this (was actually based on a _sbrk_r from Aeolus 
Development):

void * _sbrk(
    struct _reent *_s_r,
    ptrdiff_t nbytes)
{
 char  *base;    /*  errno should be set to  ENOMEM on error  */

 if (!heap_ptr){  /*  Initialize if first time through.    */
    heap_ptr = end;
    }
 base = heap_ptr;  /*  Point to end of heap.      */
 heap_ptr += nbytes;  /*  Increase heap.        */

 return base;    /*  Return pointer to start of new heap area.  */
}

It didn't work out so well.
The syscalls.c file, does it go into newlib? Is there any place to look 
for a makefile where libnewlib is generated. I'm not very familiar with 
these things so any hints are highly appreciated. Also, if there are any 
suggestions as to how one can figure out what functions a given lib-file 
provides (and even better, from what files it's been compiled!), that 
would be great! In my (very small) experience, one includes header files 
with certain names, but is then expected to link with libraries having 
different names --- is one supposed to have divine inspiration somewhere 
or is there a method to find out what libraries that are to be used?

Regards,
  Staffan

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Staffan B. wrote:
> Hello,
>
> Many thanks. I find a _sbrk_r, but no _sbrk?

_sbrk_r should be defined in the libc (newlib). It calls _sbrk which 
needs to be defined by the user. In the newlib's documentation ( 
http://sourceware.org/newlib/libc.html ) this example is given:
1
caddr_t sbrk(int incr) {
2
            extern char _end;    /* Defined by the linker */
3
            static char *heap_end;
4
            char *prev_heap_end;
5
          
6
            if (heap_end == 0) {
7
              heap_end = &_end;
8
            }
9
            prev_heap_end = heap_end;
10
            if (heap_end + incr > stack_ptr) {
11
              write (1, "Heap and stack collision\n", 25);
12
              abort ();
13
            }
14
          
15
            heap_end += incr;
16
            return (caddr_t) prev_heap_end;
17
          }

>The stub I created earlier
> looks like this (was actually based on a _sbrk_r from Aeolus
> Development):
>
> void * _sbrk(
>     struct _reent *_s_r,
>     ptrdiff_t nbytes)
> ...
This is the interface for an reentrant function with the name of the 
stub-function.

> It didn't work out so well.
Hmm, so it did work somehow? More information needed here.

> The syscalls.c file, does it go into newlib?
It usually just "go" into your project. Compile the file and link the 
generated object-code with the other object code. Just as i.e. main.c or 
uart.c or ...

> Is there any place to look
> for a makefile where libnewlib is generated. I'm not very familiar with
> these things so any hints are highly appreciated. Also, if there are any
> suggestions as to how one can figure out what functions a given lib-file
> provides (and even better, from what files it's been compiled!), that
> would be great!

You may read the GNU binutils documentation, esp. on the tools nm and 
objdump.

> In my (very small) experience, one includes header files
> with certain names, but is then expected to link with libraries having
> different names --- is one supposed to have divine inspiration somewhere
> or is there a method to find out what libraries that are to be used?

I don't think this is related to the problem. Here a function (_sbrk_r) 
of the libc (newlib) expects a support function (_sbrk). There is no 
need for an extra library, just define the system-calls as functions 
with the interfaces given in the newlib-documentation.

Hope this helps,
Martin

von Staffan B. (staffan_b)


Attached files:

Rate this post
useful
not useful
Hello,

Thanks for all the links!

I have tried a couple of ways of including the _sbrk.c. Should have 
realized that the copy of _sbrk_r wouldn't work as a stub for _sbrk... 
The compiling part naturally worked, but when I later downloaded the 
code and tried to get it running, it just hung. Debugging didn't give 
much of insight since I just ended up in an UNDEF after leaving a 
function call (that itself seemed to have worked well).

I have also tried the code snippet you suggested, but it misses the 
definition of stack_ptr and I couldn't find a clear match.

My latest attempt has been to use the syscalls.c from the file 
LPC2138_Test_IIC.zip. I have attached it as a file here.
It seems to perhaps be providing what I'm looking for, but it has some 
oddities that my compiler can't handle.
Example:
=====
  int
isatty (int fd)
{
  return 1;
  fd = fd;
}
=====
Several of these "var = var" exist in the code and it seems to be 
preventing compilation. Any clues why this is done and what to do to get 
by?

Regards,
  Staffan

von Oliver (Guest)


Rate this post
useful
not useful
"it seems to be preventing" should result in a clear arror message from 
the compiler. If not, there is no problem.

As "var = var" is prefectly valid C-Code, there should be no error. I 
guess, that this line has been put there to prevent an "unused argument" 
warning, but as is is placed after the return, there could be an 
"unreachabel code" warning instead.

Anyhow, read the error messages, this will help you to splve any 
problems.

Oliver

von Staffan B. (staffan_b)


Rate this post
useful
not useful
Hello,

You're right. I compile using Eclipse (Indigo) and in the "Problems" 
tab, I get error messages like:


Description  Resource  Path  Location  Type
Assignment to itself 'm = m'  syscalls.c  /test1/LPC2138_Test_IIC  line 
457  Code Analysis Problem

This is apparently not an error, but why does Eclipse consider it to be 
so?

Anyways, with this known, I managed to get the file compiled (other 
stupid mistakes made the linker missing the file - the object file ended 
up in the wrong directory).

The code can now be linked (syscalls.o at the absolute end of the set of 
files --- started out at the beginning before crt.o, not a good idea) 
without errors and I can download the code to the eval board.
However, I still get the same error as before. Being a little bit more 
observant, I notice that the error occurring is a Prefetch Abort 
(instruction fetch memory fault, interrupt vector mem location 0xc in 
LPC2138). When running the debugger, I consistently get the same result 
and I've tried on two different eval boards so I guess there is 
something strange in the code.

What I also notice is that the debugger 'looses track'. The calling 
hierarchy is shown (starting with main() on top, showing the different 
functions that are part in the 'calling tree' to get the the current 
code. After a while, when returning from a function call, the top level 
(starting with main()) 'disappears' and fairly quickly (not so many 
levels), the top level is changed from known location to somewhere way 
off in memory (0x1880e7f8 - there is no code whatsoever there) and when 
returning to this 'calling function', I get a PAbt interrupt - perhaps 
not so strange. When being in the function just below this strange 
location, I continuously get warnings like the following for each line 
of code that is executed:

Warn : memory read caused data abort (address: 0x1880e7f8, size: 0x4, 
count: 0x1)

I have tried to set a breakpoint in the sbrk function, but it seems for 
some reason that breakpoints are disabled so there is no easy way to 
figure out who has been calling.


I'm rather clueless as to what to do except that I guess it still in 
some way is related to the syscalls/sbrk. Any clues would be highly 
appreciated!

Regards,
   Staffan

von Oliver (Guest)


Rate this post
useful
not useful
Eclipse has an integrated Code Analysis Funktion,  which creates more 
confusion than real benefit. You can disable this in the preferences.

Oliver

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
The check for stack-heap-collision can be removed from the newlib 
example. Sorry, should have removed it after copy/paste to avoid 
confusion.

Check the value for the start-of-heap in the map-file. The symbol used 
in the newlib-example is _end. So check your linker-script if _end is 
defined there and check the value in the map-file. Maybe another label 
is used (end has been shown in a previous post, may also be called __end 
or _end__ or __heap_start_) Just make sure the used label is hold the 
correct value for start-of-heap. Maybe the name has been used elsewhere 
in the code. Esp. if "provide" is used in the linker-script the linker 
will not complain about a missing symbol but will also not set the 
correct value. Show your linker-script and the map-file if you need more 
support.

Also check that there are several kBytes of RAM "free" for the heap. 
Malloc may request heap-space in portions of 4 kBytes depending on the 
configuration of the newlib (4KiB is default IRC).

It's difficult to help without further information. Maybe the heap just 
overwrites data/bss and/or one of the stacks, maybe it's an alignment 
problem, maybe not enough free RAM.

Side-notes:
- With a correct linker-script the order of object-file-names given to 
the linker should not matter. It's only important that the 
exception-table is assigned ot the correct location. A good approach is 
an extra section for the table (using .section and ASM) and to force 
this section to the address where the core looks for it by using the 
section-name of in the linker script (with KEEP when using 
unused-code-removal).
- I have often used expressions like var=var; to avoid unused variable 
warnings from the compiler. But it seems that the method now causes the 
Eclipse and/or newer gcc (can't remember which) to give an 
self-assign-warning. Replacing var=var; by (void)var; should solve this.

von Staffan B. (staffan_b)


Attached files:

Rate this post
useful
not useful
Hello,

Clearly, I get more information than I almost can handle --- many many 
thanks for taking your time with this!
Not sure I actually do the what you suggest, but anyways:
I took a look at my linker script (attached as 2138_demo.cmd) and it 
seems to only be providing _end. Actually, when reviewing it, it seems 
like there has been issues with sbrk also in arm-elf (I've added a note 
at least, long ago...).

Looking in main.map (not attached since it is 187kB), it looks like 
this:

...
 .bss           0x40004d0c        0x0 
c:\Programs\Yagarto\lib\gcc\arm-none-eabi\4.6.2\libgcc.a(_arm_fixsfsi.o)
 .bss           0x40004d0c        0x0 
c:\Programs\Yagarto\lib\gcc\arm-none-eabi\4.6.2\libgcc.a(_arm_fixunssfsi 
.o)
 COMMON         0x40004d0c      0x100 
c:\Programs\Yagarto\arm-none-eabi\lib\libg.a(lib_a-gdtoa-gethex.o)
                0x40004d0c                __hexdig
 COMMON         0x40004e0c        0x4 
c:\Programs\Yagarto\arm-none-eabi\lib\libg.a(lib_a-reent.o)
                0x40004e0c                errno
                0x40004e10                . = ALIGN (0x4)
                0x40004e10                _bss_end = .
                0x40004e10                _end = .
                0x40004e10                PROVIDE (end, .)
LOAD crt.o
LOAD main.o
LOAD adcAD7686.o
...

Hmm, RAM could definitely be an issue I think. I have 32k available, but 
probably consume quite a bit of that (one reason for choosing the 
LPC2138 was the amount of flash and RAM). According to the spec, ram 
will be in the address space 0x4000 0000 - 0x4000 7fff. According to the 
part from main.map above, _end occurrs at 0x4000 4e10 --- does it mean 
there is space from 4e10 to 7fff free? In that case, there should be 
sufficient amount?

Just changed the var=var to (void) var and now there are no complaints 
there, thanks! Strange that eclipse should complain... Changing the 
preferences could perhaps be better since the code in itself is correct 
(thanks Oliver) - now I know why it's there though.

---OOPS, just noticed one thing. At the very end of linker script 
2138_demo.cmd, there is the line


PROVIDE ( end = . );

Should this be PROVIDE ( _end = .);  (with underscore)?

You mention that PROVIDE may turn off some checking?

You pretty much lost me with the comments at the end on the linker 
script. If there is a sample file I can look at, that would be great (my 
script apparently was sensitive to what order the makefile listed the 
object files...)

Again, many thanks for all comments and help!

Regards,
  Staffan

von Staffan B. (staffan_b)


Rate this post
useful
not useful
Hello,

Just tried changing the last line of 2138_demo.cmd to

PROVIDE ( _end = . );

(with underscore), but it didn't change anything. Same kind of error 
still.

Regards,
  Staffan

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.