Page 1 of 2
Problem With Global Variables Initializing
Posted: Thu Aug 27, 2015 3:32 pm
by RezaNoei
Hello my friends,
I have a kernel written in C and some header file that includes : stdio.h and some of other little things..
my problem : when i assign a value as initial value to a global variable, that won't work.
i used from gcc as my compiler and the process of compilation of my OS follows these steps :
1. compiling header files :
I separated header file into two file (i.e. one as foo.h and other as foo.c) then i compile that as object file :
Code: Select all
gcc -ffreestanding -c foo.c -o foo.o -m32
2. then, i compile bootloader and kernel same as above like object file :
Code: Select all
gcc -ffreestanding -c kernel.c -o kernel.o -m32
nasm -f elf Loader.asm -o Loader.o
3. finally i link those file as my OS.bin :
Code: Select all
ld -o OS.bin -Ttext 0x7c00 Loader.o Kernel.o foo.o --oformat binary -m elf_i386
if my foo.c was like this :
Code: Select all
#include "foo.h"
uint8_t Color = 0x14;
....
this variable will cause many problems, and i forced to write some functions to assign some value to those.
is there any way to initial global variable in way that works with no problem.
i checked my foo.o (object file), there are only .text Section.
Excuse me,
Another Question : is there any way to avoid from compiling headers *.c file in compilation process ? some thing like using "stdio.h" in C coding in linux ?
thank you,
Re: Problem With Global Variables Initializing
Posted: Thu Aug 27, 2015 7:53 pm
by BASICFreak
Simply put, RTFM - Learn the tools you are using (eg. What does GCC and LD do, What flags should I consider, what do the flags do, etc.)
I can assume you are using a standard GCC install and not a cross-compiler (which is fine, if you know GCCs flags - I don't use a cross compiler)
First, At the very least, at least tell the compiler not to use standard libraries and to warn you on everything (just because something is not an error does not mean it is not an ERROR - especially in OSDev).
My GCC Flags wrote:CCFLAGS=-O3 -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \
-Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline \
-Wno-long-long -Wuninitialized -Wconversion -Wstrict-prototypes -Wunsafe-loop-optimizations \
-std=gnu99 -nostdinc -fno-builtin -fno-stack-protector -march=i686 -m32 -I $(INCLUDES)
Second, Get a makefile - it makes the job so much easier, and will only compile the modified files.
Third, A linker script is also nice, you need more than the Text section most the time, plus why are you going to binary from elf-i386?
* If you want binary you should (IMHO) use aout not elf.
Forth, the program I think you are looking for is AR, which can make a "library" (actually an archive) of your object files, but you will not have to worry about this with a proper makefile.
And as for the global variable; it is probably set correctly, just in the wrong location (or not in the file since we only have .Text no Data nor BSS)
[Opinion] I consider it bad practice myself to preset variables, I rather an init function. Or if constant enum or #define them. [/Opinion]
Hopefully this points you towards the right direction.
Re: Problem With Global Variables Initializing
Posted: Thu Aug 27, 2015 10:02 pm
by kzinti
BASICFreak wrote:[Opinion] I consider it bad practice myself to preset variables, I rather an init function. Or if constant enum or #define them. [/Opinion]
Ugh?? Care to elaborate?
Re: Problem With Global Variables Initializing
Posted: Thu Aug 27, 2015 10:19 pm
by RezaNoei
BASICFreak wrote:Simply put, RTFM - Learn the tools you are using (eg. What does GCC and LD do, What flags should I consider, what do the flags do, etc.)
I can assume you are using a standard GCC install and not a cross-compiler (which is fine, if you know GCCs flags - I don't use a cross compiler)
First, At the very least, at least tell the compiler not to use standard libraries and to warn you on everything (just because something is not an error does not mean it is not an ERROR - especially in OSDev).
My GCC Flags wrote:CCFLAGS=-O3 -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \
-Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline \
-Wno-long-long -Wuninitialized -Wconversion -Wstrict-prototypes -Wunsafe-loop-optimizations \
-std=gnu99 -nostdinc -fno-builtin -fno-stack-protector -march=i686 -m32 -I $(INCLUDES)
Second, Get a makefile - it makes the job so much easier, and will only compile the modified files.
Third, A linker script is also nice, you need more than the Text section most the time, plus why are you going to binary from elf-i386?
* If you want binary you should (IMHO) use aout not elf.
Forth, the program I think you are looking for is AR, which can make a "library" (actually an archive) of your object files, but you will not have to worry about this with a proper makefile.
And as for the global variable; it is probably set correctly, just in the wrong location (or not in the file since we only have .Text no Data nor BSS)
[Opinion] I consider it bad practice myself to preset variables, I rather an init function. Or if constant enum or #define them. [/Opinion]
Hopefully this points you towards the right direction.
thank you,
that was my fault, i used from "nick blundell"s scripts in OS development series for compiling.
i have good makefile also, but i think this type of work are sometimes ugly, Anyway, Thank you I will take care.
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 2:40 am
by Octocontrabass
BASICFreak wrote:I can assume you are using a standard GCC install and not a cross-compiler (which is fine, if you know GCCs flags - I don't use a cross compiler)
You should be using a cross-compiler. If nothing else, you need the freestanding libgcc. This is not optional: all code compiled with GCC must be linked against libgcc.
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 4:50 am
by RezaNoei
Octocontrabass wrote:BASICFreak wrote:I can assume you are using a standard GCC install and not a cross-compiler (which is fine, if you know GCCs flags - I don't use a cross compiler)
You should be using a cross-compiler. If nothing else, you need the freestanding libgcc. This is not optional: all code compiled with GCC must be linked against libgcc.
I Replaced a cross-compiler as my OS compiler.
but i think when i used from -c flag in i386-elf-gcc my global decelerations has removed.
i tested that by objdump -d foo.o
i know -c will cause to stop linking process, but how can i keep my global decelerations (initial assignments) until linking process?
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 5:06 am
by Octocontrabass
RezaNoei wrote:i tested that by objdump -d foo.o
Try using objdump -h foo.o instead. Do you see any sections with names like .data?
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 6:07 am
by RezaNoei
Octocontrabass wrote:RezaNoei wrote:i tested that by objdump -d foo.o
Try using objdump -h foo.o instead. Do you see any sections with names like .data?
yes,
actually my stdio.o is :
Code: Select all
#include "../Include/string.h"
#include "../Include/stdio.h"
#define CellCount 80*25
uint8_t CurrentX=0;
uint8_t CurrentY=0;
uint8_t Color = 14;
uint8_t *VideoMemory = (uint8_t *)0xb8000;
void initial()
{
Color = 0 ;
VideoMemory = (uint16_t*)0xb8000;
}
void putch(const char ch)
{
// initial();
uint8_t *VID = VideoMemory;
*(VID++) = 'D';
*(VID++) = Color;
}
void clrscr(void)
{
size_t i;
for (i=0;i<CellCount*2;i++)
{
if (i%2)
{
VideoMemory[i] = Color;
Color = (Color+1)%16;
}
}
}
void gotoxy(uint8_t X,uint8_t Y){}
and out put of objdump -h is :
Code: Select all
file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000011f 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000153 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000002 00000000 00000000 00000153 2**0
ALLOC
3 .comment 00000012 00000000 00000000 00000153 2**0
CONTENTS, READONLY
4 .eh_frame 000000d8 00000000 00000000 00000168 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
my global variable names are usable, but assigned value to them is not the same values that is in deceleration.
Sorry, I Edited My Post.
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 6:20 am
by iansjack
So, isn't your variable there in the .bss section?
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 7:00 am
by Combuster
I only see 2 of the expected 7 bytes (3 uint8s and one pointer) in the .bss
What are your compile instructions and linker script?
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 7:05 am
by RezaNoei
iansjack wrote:So, isn't your variable there in the .bss section?
with this command:
i received this Symbol Table :
Code: Select all
file format elf32-i386
SYMBOL TABLE:
00000000 l df *ABS* 00000000 stdio.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .eh_frame 00000000 .eh_frame
00000000 l d .comment 00000000 .comment
00000000 g O .bss 00000001 CurrentX
00000001 g O .bss 00000001 CurrentY
00000001 O *COM* 00000001 Color
00000004 O *COM* 00000004 VideoMemory
00000000 g F .text 00000005 puts
00000005 g F .text 00000016 initial
0000001b g F .text 00000092 putch
000000ad g F .text 00000018 printf
000000c5 g F .text 00000046 clrscr
0000010b g F .text 00000014 gotoxy
there is no problem with variable names, the value i assigned to them in global scope isn't as i expected.
actually when i say :
Code: Select all
uint8_t * VideoMem = (uint8_t *)0xb8000;
void putc(char ch)
{
*(VideoMem++) = ch;
*(VideMem++) = 14;
}
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 7:10 am
by RezaNoei
Combuster wrote:I only see 2 of the expected 7 bytes (3 uint8s and one pointer) in the .bss
What are your compile instructions and linker script?
main makefile that i used,
Code: Select all
all:
nasm -f elf Loader.asm -o Loader.o
i386-elf-gcc -ffreestanding -c SysCore/Kernel/kernel.c -o Kernel.o -m32
i386-elf-ld -o Shams.bin -Ttext 0x7c00 -Tdata 0x7f00 Loader.o Kernel.o SysCore/Lib/Debug/stdio.o --oformat binary -m elf_i386
another makefile that i used for my header files :
Code: Select all
all:
i386-elf-gcc -c -ffreestanding stdio.c -o Debug/stdio.o -m32
when i changed the value of global variable to 0 my objdump -t stdio.o commad updated this lines :
Code: Select all
00000000 g O .bss 00000001 CurrentX
00000001 g O .bss 00000001 CurrentY
00000002 g O .bss 00000001 Color
00000004 g O .bss 00000004 VideoMemory
then "Color" and "VideoMemory" added from "com" to .bss
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 9:30 am
by iansjack
I suspect that you lost the initialized values of your variables when you converted the object file to a binary. I agree with BASICFreak that it's better to initialize variables in the program rather than letting the compiler do it.
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 10:16 am
by BASICFreak
Octocontrabass wrote:BASICFreak wrote:I can assume you are using a standard GCC install and not a cross-compiler (which is fine, if you know GCCs flags - I don't use a cross compiler)
You should be using a cross-compiler. If nothing else, you need the freestanding libgcc. This is not optional: all code compiled with GCC must be linked against libgcc.
(My compiler is a custom build, just not custom for my OS - so not the same as the Cross-Compiler WiKi, I can build for Win *nix and Mac - just need to change link script and I haven't actually tried Mac)
kiznit wrote:BASICFreak wrote:[Opinion] I consider it bad practice myself to preset variables, I rather an init function. Or if constant enum or #define them. [/Opinion]
Ugh?? Care to elaborate?
In the world of OSDev I have ran across many random issues I have never seen is userland code for *nix/Win. A lot of the time it is one of the sections of the linked file not being where the rest of the program expects. If you set the variables in the code, it will set the variable where the code THINKS it SHOULD be.
Though I haven't had this issue in a while now, the most common place I have had it was relocatable Elf modules, but I have had them in my kernel before - though I have (somehow) fixed the issue by using the tools correctly.
Re: Problem With Global Variables Initializing
Posted: Fri Aug 28, 2015 10:39 am
by kzinti
BASICFreak wrote:In the world of OSDev I have ran across many random issues I have never seen is userland code for *nix/Win. A lot of the time it is one of the sections of the linked file not being where the rest of the program expects. If you set the variables in the code, it will set the variable where the code THINKS it SHOULD be.
What about string constants (error messages for example)? They have to go to a .data or .rodata section (or somewhere). This isn't different from "initializing" globals. They are in fact globals. Note that I am not talking about C++ constructors here (which I wouldn't try to use).
Where do you draw a difference, from a technical point of view, between initializing globals and having string constants in your C/C++ code?
I think that if you run into issues with initialized globals, you have to address these issues whether or not you initialize globals.