Page 1 of 2

ChibiOS syscalls.c and GCC 7  Topic is solved

Posted: Tue Jul 17, 2018 8:06 am
by FXCoder
Hi,
When building an STM32F413 project with FPU enabled under latest ChibiStudio with GCC 7 the following link error occurs...

Code: Select all

c:/chibistudio/tools/gnu tools arm embedded/7.0 2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m/fpv4-sp/hard\libg.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'


1. This looks like a GCC library issue. Linking is OK by explicitly adding $(CHIBIOS)/os/various/syscalls.c to the source files in the build
2. This link error does not happen under GCC 6.3 so that seems to imply that GCC 6.3 is finding _sbrk OK in the GCC library
BUT
3. Shouldn't it be the case that the ChibiOS specific syscalls.c is always built and linked to projects?

So either $(CHIBIOS)/os/various/syscalls.c should be explicitly in the source list of make files
OR
Should one of the .mk files for ChibiOS system have syscalls.c added to the source list?

Thanks.

Bob

Re: ChibiOS syscalls.c and GCC 7

Posted: Tue Jul 17, 2018 10:22 pm
by faisal
You shouldn't need to include syscall.c if you aren't using any of the newlib functions that require them. In your case, it seems that someone is using malloc/free - which in turn calls _sbrk.

I actually intentionally don't include syscalls.c, so that I get linker errors in case some of the typical non-threadsafe and reentrant code from newlib gets included in my project :).

Re: ChibiOS syscalls.c and GCC 7

Posted: Wed Jul 18, 2018 5:26 am
by FXCoder
Thanks for the reply.
The project in question currently uses functions that could access malloc/free. So that's a known.
The issue (that I probably didn't make clear) is that even though the ChibiOS specific version of syscalls.c isn't explicitly included in the source files, there is no link error for _sbrk_r when using GCC 6.3.
So when ChibiOS syscalls.c isn't in the source list what is GCC 6.3 linker resolving calls to _sbrk_r to and what does that do for memory allocation?
Is it a simple function that exploits the symbol _end automatically defined by the GNU linker to allocate memory?

I thought the preferred situation would be to ensure that the ChibiOS functions in syscalls.c are built and linked.

Re: ChibiOS syscalls.c and GCC 7

Posted: Fri Jul 27, 2018 3:00 pm
by Giovanni
Is there an action required for this?

Giovanni

Re: ChibiOS syscalls.c and GCC 7

Posted: Fri Jul 27, 2018 5:12 pm
by steved
Potentially, but it could get complicated!
For applications that use malloc() or _malloc_r(), need to be sure that they hook into the Chibi allocation routines (either the default heap, or some other allocator, or a stub...) - then _sbrk_r isn't used at all. IIRC that gets a bit tricky, and might be worse if attempting a generic solution.

Re: ChibiOS syscalls.c and GCC 7

Posted: Wed Aug 08, 2018 7:43 am
by FXCoder
I was going for the simple approach.
Since there is a ChibiOS specific _sbrk_r in $(CHIBIOS)/os/various/syscalls.c then why not have it built by all makefiles.
Then the customised _sbrk_r gets linked if any system level functions call it.
If there are no calls to _sbrk_r then there is no overhead.
Letting the GNU library version get linked silently seems like a bad idea.

Re: ChibiOS syscalls.c and GCC 7

Posted: Wed Aug 08, 2018 8:32 am
by steved
I'm not sure whether the customised _sbrk_r() will work under all circumstances.
My understanding is that the standard routines assume the heap is a contiguous block of memory; the base of which is fixed, and the top of which is extended by calls to _sbrk_r(). (See https://sourceware.org/newlib/libc.html ... t-Syscalls)

In practice this may well be achieved with calls to chCoreAlloc(); however if the application is also calling Chibi's memory allocation routines directly, is it possible to end up with a fragmented heap area?

The 'standard' malloc() also looked fairly complex (although no doubt efficient), so replacing it with Chibi's handler makes sense in some ways.

Re: ChibiOS syscalls.c and GCC 7

Posted: Wed Aug 08, 2018 9:24 am
by FXCoder
WRT the ChibiOS variant if CH_CFG_USE_MEMCORE isn't defined then ENOMEM is set as the error.
So there could be trouble up the chain if the memory out isn't caught and acted upon.

The GNU lib for GCC 6.3 has a generic alternative as you described which relies on linker vars to figure out where to add memory.
It will work but silent memory allocations like that are a potential source of mysteries.

Unfortunately the GCC 7 lib has nothing defined (well not for the FPU enabled code I was linking anyway) so it just fails in linking.
This is sort of OK to figure out and fix.
However, for anyone not knowing about the ChibiOS syscalls.c it is just another opportunity to go hunting for an answer.

I'd prefer to see the syscalls.c in the standard makefiles even if commented out.
At least then the clue is right there.

Code: Select all

caddr_t _sbrk_r(struct _reent *r, int incr)
{
#if CH_CFG_USE_MEMCORE
  void *p;

  chDbgCheck(incr >= 0);

  p = chCoreAlloc((size_t)incr);
  if (p == NULL) {
    __errno_r(r) = ENOMEM;
    return (caddr_t)-1;
  }
  return (caddr_t)p;
#else
  (void)incr;
  __errno_r(r) = ENOMEM;
  return (caddr_t)-1;
#endif
}

Re: ChibiOS syscalls.c and GCC 7

Posted: Wed Aug 08, 2018 11:05 am
by Giovanni
i think the library should not assume a contiguous range when using sbrk(), it is possible for the application to call smrk() directly and that would create a "hole" under such an assumption, chCoreAlloc() should be fine as sbrk() implementation.

Giovanni

Re: ChibiOS syscalls.c and GCC 7

Posted: Wed Aug 08, 2018 2:02 pm
by steved
Giovanni wrote:i think the library should not assume a contiguous range when using sbrk(), it is possible for the application to call smrk() directly and that would create a "hole" under such an assumption, chCoreAlloc() should be fine as sbrk() implementation.

I don't feel totally confident about that. If you look at the descriptions of how _sbrk() and friends work (https://linux.die.net/man/2/sbrk, https://www.cs.utah.edu/flux/moss/node39.html, https://en.wikipedia.org/wiki/Sbrk), they are simply extending a contiguous block of memory. This all happens under the hood, with an upper layer (usually malloc() and the like) adding the memory to its available pool.
Looking at the malloc() included with newlib, a couple of the comments rather confirm this; I won't post the whole routine, but some selected bits:

Code: Select all

/*
  Extend the top-most chunk by obtaining memory from system.
  Main interface to sbrk (but see also malloc_trim).
*/
static void malloc_extend_top(RARG INTERNAL_SIZE_T nb)
:
:
  /* Fail if sbrk failed or if a foreign sbrk call killed our space */
  if (brk == (char*)(MORECORE_FAILURE) ||
      (brk < old_end && old_top != initial_top))
    return;

The GNU malloc appears to be less simplistic (https://sourceware.org/glibc/wiki/MallocInternals), but there still appears to be scope for problems.
Maybe I'm over-concerned, but I've intercepted malloc() and free() and directed them straight to Chibi's routines. This totally eliminates the need for _sbrk(), and should be a bit faster than the standard malloc().