Using variable lists for printing stuff in the kernel

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
chid1989
Posts: 2
Joined: Fri Sep 06, 2013 4:14 pm

Using variable lists for printing stuff in the kernel

Post by chid1989 »

Hi,

I am trying to implement a printf in my kernel as a part of learning purpose. I am stuck at a point where I have to incorporate the variable list.

I have included the following in include/stdarg.h

#define va_alist __builtin_va_alist
#define va_dcl __builtin_va_alist_t __builtin_va_alist; ...
#define va_start(ap) __builtin_varargs_start(ap)
#define va_arg(ap, type) __builtin_va_arg((ap), type)
#define va_end(ap) __builtin_va_end(ap)

Its a new file and contains only the above. When I include this file in my sys/main.c and try to use va_alist, it is throwing me an error saying "sys/main.c:114: error: '__builtin_va_alist' undeclared (first use in this function)".

My main.c's 114 line is: va_alist arg_p;

Can you help me with what is the problem.

Thanks
Chidambaram
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Using variable lists for printing stuff in the kernel

Post by sortie »

Uh, isn't it va_list instead of va_alist?
chid1989
Posts: 2
Joined: Fri Sep 06, 2013 4:14 pm

Re: Using variable lists for printing stuff in the kernel

Post by chid1989 »

Hi,

I am trying to do this for a 64 bit machine. So we should use __builtin_va_alist right ( I may be wrong in this )? My compiler flags are "CFLAGS=-O1 -Wall -Werror -nostdinc -Iinclude -msoft-float -mno-sse -fno-builtin -fPIC -mtune=amdfam10 -g3"

Thanks
Chidambaram
singerng
Posts: 21
Joined: Sun Jan 20, 2013 6:27 pm

Re: Using variable lists for printing stuff in the kernel

Post by singerng »

I believe the use of the flag "-fno-builtin" is preventing whatever you're compiling to have access to the __builtin_va_list symbol.

Additionally, according to the page http://gcc.gnu.org/onlinedocs/gcc-4.8.1 ... r-Builtins:
GCC provides a large number of built-in functions other than the ones mentioned above. Some of these are for internal use in the processing of exceptions or variable-length argument lists and are not documented here because they may change from time to time; we do not recommend general use of these functions.
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: Using variable lists for printing stuff in the kernel

Post by thepowersgang »

You don't need -fno-builtin for a kernel, just -ffreestanding. With this option, you can quite easily use stdarg.h (and stdint.h with newer versions of GCC), as they don't have any runtime dependencies.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Using variable lists for printing stuff in the kernel

Post by xenos »

singerng wrote:I believe the use of the flag "-fno-builtin" is preventing whatever you're compiling to have access to the __builtin_va_list symbol.
Not quite. See http://gcc.gnu.org/onlinedocs/gcc/C-Dia ... ct-Options:
-fno-builtin
-fno-builtin-function
Don't recognize built-in functions that do not begin with ‘__builtin_’ as prefix. See Other built-in functions provided by GCC, for details of the functions affected, including those which are not built-in functions when -ansi or -std options for strict ISO C conformance are used because they do not have an ISO standard meaning.
I actually use -fno-builtin for my kernel.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Using variable lists for printing stuff in the kernel

Post by bluemoon »

XenOS wrote:I actually use -fno-builtin for my kernel.
This will prevent using of optimized versions of memcpy etc.

As the model answer of this forum, why nobody mention cross compiler, and get rid of the ugly switches?
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Using variable lists for printing stuff in the kernel

Post by sortie »

Hi, time to clear up some confusion.

Don't pass -nostdinc. It prevents you from getting the standard freestanding compiler headers (<stdarg.h>, <stddef.h>, and so on) and the headers from the system root (where your system libc and other things are located). Newbies tend to use -nostdinc to prevent getting headers from /usr/include on the host system, but that's totally missing point, because you ought to use a cross-compiler as they don't think they are building a Linux system, but rather know they are building something else. Nothing good can come from the compiler incorrectly thinking it is building Linux: Don't lie to the compiler.

Don't write your own <stdarg.h>. This is deep compiler magic, you cannot reliably do it without using compiler builtins, which you fail at. Instead, now that you have remove -nostdinc, you can just #include <stdarg.h> and get the compiler's blessed <stdarg.h>.

The -fbuiltin switch automatically replaces uses of common functions with their __builtin_ variable. The compiler knows the semantics of the __builtin_ functions, as they are part of the compiler. This allows the compiler to perform a lot of really useful optimizations. You really want to compile with -fbuiltin. It's so useful it's on by default. However, because freestanding C might be different from hosted C, gcc disables -fbuiltin with -fno-builtin whenever you pass -ffreestanding. Note how -ffreestanding is the only situation where you would want automatic builtins disabled, and they are disabled automatically in that case. For that reason, you have no reason to ever pass -fno-builtin as -ffreestanding does it for you. However, if your kernel doesn't violate any standard semantics in standard C functions, you may really wish to to add -fbuiltin to re-enable them in freestanding mode, as it'll allow the kernel to be properly optimized.

Note how -fno-builtin doesn't know disable __builtin_foo, but rather disables foo becoming __builtin_foo automatically.

Note how -Werror is useful for making sure there are no warnings, but how warnings are not errors. For instance, "#warrning This is not a release version" shouldn't give you a compile error. There are lots of warnings out there that you probably don't enable, and if you did, you wouldn't consider them real errors and spend a lot of time fixing non-existent errors. Also note how if you use -Werror and clean your codebase of errors, but if someone else builds your project with a newer compiler that has more warnings, then your project will mysteriously fail to build for them. For that reason, never leave -Werror on by default, but just it privately to rid yourself of warnings in a manner that won't unexpectedly annoy others. My recommendation is to look through the gcc warnings. If you consider -Wfoo a real error, despite being a warning by default, I advise you to pass -Werror=foo instead of -Werror.

bluemoon: I was a bit tired and missed that I had to make one of these posts. :-)
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Using variable lists for printing stuff in the kernel

Post by xenos »

bluemoon wrote:This will prevent using of optimized versions of memcpy etc.
Not really:
sortie wrote:Note how -fno-builtin doesn't know disable __builtin_foo, but rather disables foo becoming __builtin_foo automatically.
Actually I could still use __builtin_memcpy etc. if I wanted to use those, but I don't have any of those in my kernel. The effect of -fno-builtin is only to disable the shortcuts which are not prefixed by __builtin_, and this is actually something I want, so that I could write my own substitutes for those, if necessary, and avoid name collisions.
sortie wrote:However, because freestanding C might be different from hosted C, gcc disables -fbuiltin with -fno-builtin whenever you pass -ffreestanding. Note how -ffreestanding is the only situation where you would want automatic builtins disabled, and they are disabled automatically in that case. For that reason, you have no reason to ever pass -fno-builtin as -ffreestanding does it for you.
Nice, I didn't know that - I pass -ffreestanding anyway (and I do use a cross compiler), so the -fno-builtin is just superfluous here.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
singerng
Posts: 21
Joined: Sun Jan 20, 2013 6:27 pm

Re: Using variable lists for printing stuff in the kernel

Post by singerng »

Sorry about the misunderstanding with -fno-builtin, I really should have looked closer at the GCC documentation.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: Using variable lists for printing stuff in the kernel

Post by h0bby1 »

sortie wrote:Hi, time to clear up some confusion.

Don't pass -nostdinc. It prevents you from getting the standard freestanding compiler headers (<stdarg.h>, <stddef.h>, and so on) and the headers from the system root (where your system libc and other things are located). Newbies tend to use -nostdinc to prevent getting headers from /usr/include on the host system, but that's totally missing point, because you ought to use a cross-compiler as they don't think they are building a Linux system, but rather know they are building something else. Nothing good can come from the compiler incorrectly thinking it is building Linux: Don't lie to the compiler.

Don't write your own <stdarg.h>. This is deep compiler magic, you cannot reliably do it without using compiler builtins, which you fail at. Instead, now that you have remove -nostdinc, you can just #include <stdarg.h> and get the compiler's blessed <stdarg.h>.

The -fbuiltin switch automatically replaces uses of common functions with their __builtin_ variable. The compiler knows the semantics of the __builtin_ functions, as they are part of the compiler. This allows the compiler to perform a lot of really useful optimizations. You really want to compile with -fbuiltin. It's so useful it's on by default. However, because freestanding C might be different from hosted C, gcc disables -fbuiltin with -fno-builtin whenever you pass -ffreestanding. Note how -ffreestanding is the only situation where you would want automatic builtins disabled, and they are disabled automatically in that case. For that reason, you have no reason to ever pass -fno-builtin as -ffreestanding does it for you. However, if your kernel doesn't violate any standard semantics in standard C functions, you may really wish to to add -fbuiltin to re-enable them in freestanding mode, as it'll allow the kernel to be properly optimized.

Note how -fno-builtin doesn't know disable __builtin_foo, but rather disables foo becoming __builtin_foo automatically.

Note how -Werror is useful for making sure there are no warnings, but how warnings are not errors. For instance, "#warrning This is not a release version" shouldn't give you a compile error. There are lots of warnings out there that you probably don't enable, and if you did, you wouldn't consider them real errors and spend a lot of time fixing non-existent errors. Also note how if you use -Werror and clean your codebase of errors, but if someone else builds your project with a newer compiler that has more warnings, then your project will mysteriously fail to build for them. For that reason, never leave -Werror on by default, but just it privately to rid yourself of warnings in a manner that won't unexpectedly annoy others. My recommendation is to look through the gcc warnings. If you consider -Wfoo a real error, despite being a warning by default, I advise you to pass -Werror=foo instead of -Werror.

bluemoon: I was a bit tired and missed that I had to make one of these posts. :-)
personally, i rewrite all the c header, using different prototype declaration (just adding a suffix to the function name), to avoid conflict with compiler specific thing, most portable library use preprocessor definitions to know the name of the c functions, and even c headers have different name,it need little tweaking for each time i need to port a library, but the protype declaration are totally compatible regarding parameters type and return type, it's just the name that change not to confuse the compiler

i can compile the whole thing with any compiler without having to depend on how the compiler will interpret the call, it can prevent some optimizations, but at least it's totally compiler independent, and can be built with intel compiler, visual studio or gcc without problem, i know all call to the libc will not be misunderstood for builtin semantic and will be actual call to my function definitions no matter which compiler i use, and i use nostdlib flag with gcc and doesn't link any runtime library at all from any compiler, and i have to add manually some of the built in function when they are used that i copy from existing runtime when they are used, but i'd rather program my thing in sort that it doesn't need to rely on compiler specific semantic or built in function

it's bit more work to compile some lib, but not that much as there is often way to easily change the name of c function being used with pre processor macros, and it's much easier to compile it with any compiler without having to deal with conflicting runtime/builtin function being used by different compilers and i can compile it even with a native gcc without problem at all, but yes it has to also get rid of all compiler specific optimization regarding built in function semantic, which is not all that much of a big loss all together, if i really want to optimize a routine, i'd rather not have to rely on compiler specific semantic to perform the optimization

the only built in type i ever use is for the int64 type, and i mannage to do all operation on them that are supposed to require a runtime call with my own functions, and also for the __declspec/attribute() that is different between visual and gcc, but that's about it, because there is no other way to make the compiler do what i want, but otherwise i avoid all the compiler specific thing whenever i can
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Using variable lists for printing stuff in the kernel

Post by gerryg400 »

h0bby1, does this work for all platforms and all ABI's ? For example, the stdarg ABI for x86_64.
If a trainstation is where trains stop, what is a workstation ?
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: Using variable lists for printing stuff in the kernel

Post by h0bby1 »

gerryg400 wrote:h0bby1, does this work for all platforms and all ABI's ? For example, the stdarg ABI for x86_64.
i made my own abi anyway, i use a tool to convert so and dll to my own abi, and it also correct name mangling to have unified name accross the two system, and i don't really use std arg either, but if i did, i'd recode the whole thing to be compiler independant, for now it works well if i compile under linux and window with either native gcc, icc, or visual studio

i really don't want to depend on any compiler specific thing, because it become to bothering to handle otherwise if you need to manage builds made with different compilers, i had too much issue in the past with devcpp/code warrior/borland/visual studio(s!)/cygwin etc , i tested this system before with other project and normally it should work fine with any compiler, and can link any module compiled with any compiler with any other module compiled with any other compiler

there can still be issues with c++ with how the class pointer is passed, and i don't use x64 either, but if calling convention declaration are consistent normally it doesn't make any problem as name mangling for import/export are unified with the tool to create my abi

i always consider stdargs and stdio to be very weak any way and can make many many security problem if they are not handled well so i'd rather get rid of them all together =)

for regular io , file/socket etc i'd rather have something on the line of the windows system with the overlapped structure, with asynchronous transfer management, and something more modern than stdio function, and for the printf etc that use stdarg i'd rather not use them at all

if i really needed to implement something like stdargs, i'd rather do something like an explicit typed parameter list rather than stdarg/stdio

but i guess stdarg thing must be compiler dependent anyway , not sure if there is standard way it's supposed to be handled, but if i needed to have the standard c implementation, i'd rather look at how the compiler handle it, and make the code to gather it, eventually with preprocessors switch or compiler specific version of the file that handle the stdarg functions if there are really stdarg code that cannot be avoided, but i wouldn't like that a lot cause there would be big chance to break inter compiler compatibility, or would need to keep track of the specific stdarg used in the call to handle it correctly, but it's a system that is too messy and too weak with typing for that i really want to use that

if there is a file that use stdard compiled as64 bit with gcc that need to call a function using stdard compiled with 32 bit with visual studio, it would be hell to handle correctly, so no thanks for me lol

in the absolute, it could be done by making some check by finding the calling module from the return address, and determining which kind of stdard it use, each module could be compiled with an exported symbol set automatically from compiler flag from preproc definition, the called function could gather it to determine how the stdarg were passed, if i really needed to implement some stdarg i'd probably go that way, unless there is an easy and reliable way to determine automatically how the args were passed or to force the compiler to pass it in a certain way using calling convention specifier in the function definition

it might seem like olalala, if i don't handle it correctly it will break everything and so i'd rather rely on compiler built in, but actually if you don't handle that correctly (arg passing etc) , it will break once you change a compiler flag or change compiler, or it need to be draconian on the compilation options, and that everyone who want to build anything for the os use the exact same cross compiler compiled with exact same options, which is a constraint that i'd rather avoid all together

with this system it introduce a little bit of specific base C function naming , but that can easily be dealt with using preprocessor definition, and after you don't have to care at all about any compiler specific thing at all, and it can be compiled using any compiler with zero #ifdef all expect for calling convention and function delcaration attributes

in theory it can use the runtime linked statically if needed , it shouldn't hurt, except it increase the exe size a little bit, and then can lead to problem if you want to link statically module compiled with different compiler together, it shouldn't be a problem in the case of os dev, as it's unlikely someone will have to link statically with a precompiled lib, but without the runtime at all, it can even link static lib compiled with any compiler together without pb, provided the linker can understand the format of the objects, like compiling some static lib with different version of gcc or different compiler that can output static .lib files
Post Reply