Author Topic: Libfxcg bugs with fixes.  (Read 3628 times)

0 Members and 2 Guests are viewing this topic.

Offline ProgrammerNerd

  • LV3 Member (Next: 100)
  • ***
  • Posts: 50
  • Rating: +9/-2
    • View Profile
Libfxcg bugs with fixes.
« on: August 24, 2014, 03:16:43 pm »
Libfxcg is by no means perfect.
I would normally just submit a pull request however there is no guarantee that affect people will be aware that it is a bug in libfxcg and not their code and how to fix it. I have long had these fixed in my fork but never bothered to really document my changes. I think having a topic will get noticed by more people so that they can too make these fixes and point out any other bugs that they may have found.
All bugs listed here affect the most recent version of libfxcg as of the time of writing this post and can be found here: https://github.com/Jonimoose/libfxcg
Of course older versions are affected as well. I know for a fact that the linker script fix affects even the old PrizmSdk 0.3 from 2011 located here http://www.cemetech.net/news.php?id=486 I could not see if other bugs affect this version as the source is not included for it's libc and I have not made tests for it and see no need to as it is obsolete.
Lets not limit ourselves to bugs or terrible code that affect both. If you see a bug that affects only libfxcg it is best reported. Really no-one should be using the old PrizmSdk 0.3 from 2011 however should you find a bug that affects it and you want to post it go ahead it may give people another reason to upgrade.
1. fread is broken.
The way fread should work is that every time it is called the data following the read data is read the next call. However the function will always read from the beginning of the file. As of writting the file located here https://github.com/Jonimoose/libfxcg/blob/master/libc/stdio.c says in fwrite
Code: [Select]
size_t ret = Bfile_ReadFile_OS(handle_tonative(stream->fileno), buffer, n, 0);
However it should be
Code: [Select]
    size_t ret = Bfile_ReadFile_OS(handle_tonative(stream->fileno), buffer, n, -1);
The only difference is that I changed the zero to a negative one. What this means is that it continues to read where it left off.
2. Linker script does not correctly handle BSS.
When you have static variables in a library you may be surprised to find that global and static variables are not initialized. Fix this by changing
Code: [Select]
        .bss : {
                _bbss = . ;
                *(.bss) *(COMMON);
                _ebss = . ;
        } >ram
To
Code: [Select]
        .bss : {
                _bbss = . ;
                *(.bss)
                *(.bss*)
                *(COMMON)
                _ebss = . ;
        } >ram
The reason why this works is that the linker will insert things such as .bss_variable_name when compiled in a library. This puts it in the proper section and upon start-up it will be cleared just like it should.
3. The memove implementation is terrible.
Actually I had worse insults that I was tempted to put but I am sure whoever wrote it makes better code by now and I do not want to hold this against them but
Code: [Select]
void* memmove(void* destination, const void* source, size_t num) {
void* d = malloc(num);
memcpy(d, source, num);
memcpy(destination, d, num);
free(d);
return destination;
}
Yes that is right, I did not make this code up for slander purposes. It is really in there in string.c
Lets replace it with something better
Code: [Select]
void *memmove(void *dst, const void *src, size_t count){
//From dietlibc
char *a = dst;
const char *b = src;
if (src!=dst){
if (src>dst){
while (count--) *a++ = *b++;
}else{
a+=count-1;
b+=count-1;
while (count--) *a-- = *b--;
}
}
return dst;
}
The reason it is considered a bug is because if you need to copy something larger than the small heap the function will fail.
4.The exit function crashes the calculator on purpose.
Code: [Select]
void exit(int status) {
    fprintf(stderr, "TERMINATED (%i)", status);
    // We don't have a clean way to exit (right now), so just crash it.
    ((void (*)())1)(); // Unaligned instruction
}
Actually we do have a clean way to exit. When this function is called there is usually a problem so the user should be able to see the error code. To do this we print the error message and use the GetKey function, from there the user can press the menu key when they are done reading the error code so just replace it with:
Code: [Select]
void exit(int status) {
fprintf(stderr, "TERMINATED (%i)\nPress menu key to exit\n", status);
int key;
while(1)
GetKey(&key);
}
Also edit the header stdlib.h change
Code: [Select]
void exit(int status);
to
Code: [Select]
void exit(int status) __attribute__ ((noreturn));
Also while you are there fix the abs definition so that it matches the source code.
Change
Code: [Select]
long abs(long n);
To
Code: [Select]
int abs(int x);
And now add #include <stdlib.h> to the top of stdlib.c
The reason for doing this is so that when compiling stdlib.c gcc knows that this function does not return in addition to the program you compile with gcc and libfxcg that involves exit. Yes we could just duplicate the __attribute__ ((noreturn)) to also be in stdlib.c but I feel that this is a cleaner solution. Also if stdlib.c fails to compile due to you including it, that means the headers suck and need improvement which is why I fixed the abs definition.
5. You cannot actually see the errors.
I don't really consider this a bug per say, however I believe it is much better to be able to see the error messages on screen instead of sending anything from stderr to the serial port.
So replace both fwrite_term and fwrite with
Code: [Select]
static size_t fwrite_term(const void *ptr, size_t size, size_t nitems,FILE *stream,int col){
static int termXfxcg,termYfxcg;
    char *buffer = alloca(1 + nitems * size);
if (buffer == NULL) {
IOERR(stream, ENOMEM);
return 0;
}

memcpy(buffer, ptr, nitems * size);
buffer[nitems * size] = '\0';
const char *outp = buffer;
char *eol;

// Loop over all lines in buffer, terminate once we've printed all lines.
do{
eol = strchr(outp, '\n');
if(eol) {
*eol = '\0';
}

// Cast to wider type for correct pointers
PrintMiniMini(&termXfxcg, &termYfxcg, outp, 0, col, 0);

// CR/LF if applicable
if(eol){
termXfxcg = 0;
termYfxcg += 10;
outp = eol + 1;
}
if(termYfxcg>=200)
termYfxcg=0;
}while (eol);
return nitems;
}
// TODO make ptr, stream restrict for optimization
size_t fwrite(const void *ptr,size_t size,size_t nitems,FILE *stream){
if (isstdstream(stream)) {
if(stream->fileno==2){
// stderr: display but red font
//return fwrite_serial(ptr, size, nitems, stream);
return fwrite_term(ptr, size, nitems, stream,TEXT_COLOR_RED);
}else if(stream->fileno==1){
// stdout: display
return fwrite_term(ptr, size, nitems, stream,TEXT_COLOR_BLACK);
}else{
// stdin..?
}
}
// TODO this must be able to fail, but how?
Bfile_WriteFile_OS(handle_tonative(stream->fileno), ptr, size * nitems);
return nitems;
}
Now in stdio.h remove the lines that say
Code: [Select]
unsigned short termx, termy;
6. fopen is also broken.
It is common knowledge that forgetting to null terminate a string that should be null terminated will cause a bug.
Look for:
Code: [Select]
Bfile_StrToName_ncpy(chars16, path, plen);
and replace it with
Code: [Select]
Bfile_StrToName_ncpy(chars16, path, plen+1);
This will null terminate the string.
« Last Edit: August 24, 2014, 06:50:48 pm by ProgrammerNerd »

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: Libfxcg bugs with fixes.
« Reply #1 on: August 24, 2014, 04:17:29 pm »
Good work, also beware, you apparently copy-pasted the text twice in the same post.

Offline ProgrammerNerd

  • LV3 Member (Next: 100)
  • ***
  • Posts: 50
  • Rating: +9/-2
    • View Profile
Re: Libfxcg bugs with fixes.
« Reply #2 on: August 24, 2014, 06:54:07 pm »
I fixed my post. Also I have a strange feeling that there are more bugs than this.

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: Libfxcg bugs with fixes.
« Reply #3 on: August 25, 2014, 04:37:49 am »
Well that would be very surprizing if there weren't. I guess some bugs are to be investigated to see if it's not libfxcg's fault.