Discussion:
Huge numbers for incr passed to _sbrk
Michael Mamic
2018-08-16 07:32:20 UTC
Permalink
Hello,

I am making a bare metal operating system for then Raspberry Pi, using
newlib as the standard library. I have implemented all of the syscalls
without trouble, the exception being _sbrk which always yields an error. My
simple implementation is below:

uint32_t sbrk(int incr) {
highest_addr+=incr;
if(highest_addr > 0x20000000) {
errno = ENOMEM;
return -1;
}
return highest_addr;
}

This implementation of sbrk is seemingly fine, but sbrk itself is called
with an incredibly large value for incr, 1431656813. This huge number
causes my memory to immediately overflow. After debugging, I have found
with almost absolute certainty that this call to sbrk comes when I call
printf, sometime before the text is sent to _write for dislay. My
installation of newlib comes from the libnewlib debian package, and it is
on the most recent update.

What could be the problem here, and is my implementation of sbrk adequate?
Freddie Chopin
2018-08-16 07:41:34 UTC
Permalink
Hello!

Your implementation of sbrk() is actually wrong. It should return
`highest_addr` value from _BEFORE_ it was incremented. For an example
see here:

https://github.com/DISTORTEC/distortos/blob/master/source/newlib/sbrk_r.cpp

In your case you should make a copy of original `highest_addr` value,
do some checking (also before actually modifying `highest_addr`) and
only then increment `highest_addr`. The returned value should be the
copy that you made at the very beginning.

Whether it fixes your original problem is another matter.

Regards,
FCh
Emeka
2018-08-21 21:12:46 UTC
Permalink
Can you share what you are doing with me ?
Post by Michael Mamic
Hello,
I am making a bare metal operating system for then Raspberry Pi, using
newlib as the standard library. I have implemented all of the syscalls
without trouble, the exception being _sbrk which always yields an error. My
uint32_t sbrk(int incr) {
highest_addr+=incr;
if(highest_addr > 0x20000000) {
errno = ENOMEM;
return -1;
}
return highest_addr;
}
This implementation of sbrk is seemingly fine, but sbrk itself is called
with an incredibly large value for incr, 1431656813. This huge number
causes my memory to immediately overflow. After debugging, I have found
with almost absolute certainty that this call to sbrk comes when I call
printf, sometime before the text is sent to _write for dislay. My
installation of newlib comes from the libnewlib debian package, and it is
on the most recent update.
What could be the problem here, and is my implementation of sbrk adequate?
Michael Mamic
2018-08-23 06:19:40 UTC
Permalink
I have posted the project source up on github.

https://github.com/Mikestylz/CirnOS
Post by Emeka
Can you share what you are doing with me ?
Post by Michael Mamic
Hello,
I am making a bare metal operating system for then Raspberry Pi, using
newlib as the standard library. I have implemented all of the syscalls
without trouble, the exception being _sbrk which always yields an error. My
uint32_t sbrk(int incr) {
highest_addr+=incr;
if(highest_addr > 0x20000000) {
errno = ENOMEM;
return -1;
}
return highest_addr;
}
This implementation of sbrk is seemingly fine, but sbrk itself is called
with an incredibly large value for incr, 1431656813. This huge number
causes my memory to immediately overflow. After debugging, I have found
with almost absolute certainty that this call to sbrk comes when I call
printf, sometime before the text is sent to _write for dislay. My
installation of newlib comes from the libnewlib debian package, and it is
on the most recent update.
What could be the problem here, and is my implementation of sbrk adequate?
Freddie Chopin
2018-08-23 07:31:42 UTC
Permalink
Hi Michael

Your sbrk() code is still wrong... Did you get my e-mail (via the
list)?

https://sourceware.org/ml/newlib/2018/msg00772.html

Regards,
FCh
Michael Mamic
2018-08-23 17:22:29 UTC
Permalink
I did not receive that email, but I have followed it's advice and updated
the syscalls file. I still have the same error as before.

A similar incr value of huge proportions is passed to sbrk when Lua is
initialized. I need to find out why this is happening so I can adjust for
it.
Post by Freddie Chopin
Hi Michael
Your sbrk() code is still wrong... Did you get my e-mail (via the
list)?
https://sourceware.org/ml/newlib/2018/msg00772.html
Regards,
FCh
Freddie Chopin
2018-08-23 17:39:51 UTC
Permalink
Post by Michael Mamic
I did not receive that email, but I have followed it's advice and updated
the syscalls file. I still have the same error as before.
A similar incr value of huge proportions is passed to sbrk when Lua is
initialized. I need to find out why this is happening so I can adjust for
it.
I think you have a problem elsewhere. For example in here you use
f_write() function from FatFS in a wrong way:

https://github.com/Mikestylz/CirnOS/blob/master/syscalls.c#L48

The pointer you pass as the last argument should always be valid, as an
example see here:

http://elm-chan.org/fsw/ff/doc/open.html

FatFS does absolutely no error checking on this pointer and will
happily write to NULL. The second issue is that the value you return
from your _write() will also be extremely wrong, as you just happen to
return a value that is available from address NULL... I there are more
problems like this in the code, then basically anything can happen.

Regards,
FCh
Bob Dunlop
2018-08-23 20:53:45 UTC
Permalink
Post by Michael Mamic
A similar incr value of huge proportions is passed to sbrk when Lua is
initialized. I need to find out why this is happening so I can adjust for
it.
Are the library and syscall implementation being compiled with the
same compiler flags and using a common header file for the function
prototype ?

A mismatch in type or parameter passing conventions between caller and
callie could lead to these sorts of errors. But then I'd have expected
just about every function to be affected.

The value seen in the syscall 1431656813 converted to hex is 0x5555596D.
Now all those 5s make me think of stack or memory boundry guard values.
--
Bob Dunlop
Michael Mamic
2018-08-24 19:16:21 UTC
Permalink
I have fixed the bug now. It turns out that I was using uint32_t types for
my sbrk implementation when I should have been using char* types. The
official Newlib documentation uses caddr_t in its sample implementation of
sbrk, which was confusing to me as that is a type I had never seen before.
I had to browse through a forum from 1999 to figure out that caddr_t is
just a typedef to char*.

I think it would help all new users of Newlib if the documentation used
char* instead of caddr_t, or at least had a sentence saying what caddr_t is.
Post by Bob Dunlop
Post by Michael Mamic
A similar incr value of huge proportions is passed to sbrk when Lua is
initialized. I need to find out why this is happening so I can adjust for
it.
Are the library and syscall implementation being compiled with the
same compiler flags and using a common header file for the function
prototype ?
A mismatch in type or parameter passing conventions between caller and
callie could lead to these sorts of errors. But then I'd have expected
just about every function to be affected.
The value seen in the syscall 1431656813 converted to hex is 0x5555596D.
Now all those 5s make me think of stack or memory boundry guard values.
--
Bob Dunlop
Joel Sherrill
2018-08-24 19:24:40 UTC
Permalink
Post by Michael Mamic
I have fixed the bug now. It turns out that I was using uint32_t types for
my sbrk implementation when I should have been using char* types. The
official Newlib documentation uses caddr_t in its sample implementation of
sbrk, which was confusing to me as that is a type I had never seen before.
I had to browse through a forum from 1999 to figure out that caddr_t is
just a typedef to char*.
I think it would help all new users of Newlib if the documentation used
char* instead of caddr_t, or at least had a sentence saying what caddr_t is.
The default typedef is in newlib/libc/include/sys/types.h. Some OSes
define it themselves. caddr_t seems easy to find. Which seems irrelevant
since sbrk() is prototped in sys/unistd.h as:

./sys/unistd.h:void * _sbrk (ptrdiff_t __incr);

Looks like there are a fair number of incorrect types in the various sbrk
implementations in libgloss.

Where did you find your sbrk() starting point?

And was there not a mismatched prototype warning when you compiled it?

--joel
Post by Michael Mamic
Post by Bob Dunlop
Post by Michael Mamic
A similar incr value of huge proportions is passed to sbrk when Lua is
initialized. I need to find out why this is happening so I can adjust
for
Post by Bob Dunlop
Post by Michael Mamic
it.
Are the library and syscall implementation being compiled with the
same compiler flags and using a common header file for the function
prototype ?
A mismatch in type or parameter passing conventions between caller and
callie could lead to these sorts of errors. But then I'd have expected
just about every function to be affected.
The value seen in the syscall 1431656813 converted to hex is 0x5555596D.
Now all those 5s make me think of stack or memory boundry guard values.
--
Bob Dunlop
Loading...