Page 1 of 2
'Libary' problems, and syscalls.
Posted: Tue Jan 29, 2008 6:45 pm
by piranha
Hello, everyone.
This has been annoying me for a while.
I have implemented syscalls and am now testing binary file loading and libraries to use syscalls and etc.
Now, my problem:
I have (for now) set syscall 1 to be a sys_print function (to write a character to the screen). I also have a basic library to call that syscall:
Code: Select all
int putch(char c)
{
asm("int $0x80"::"a"(1), "b"(c));
return 1;
}
This is tested and works.
I also have a program (init.c) which does run on my OS. Now, I have made it print 'Hello' on the screen with a bunch of putch() calls. My problem function is this:
Code: Select all
int puts(char str[256])
{
int i=0;
while(str[i] != '\0')
{
putch(str[i]);
i++;
}
return 1;
}
When I call this function, nothing appears on the screen after the 'Hello' print out.
Here is the main() function:
Code: Select all
int main_init()
{
putch('H');putch('e');putch('l');putch('l');putch('o');putch('!');putch('\n');
puts("Hello, Testing. Hello World!");
}
I can't figure it out!
It compiles with this:
Code: Select all
gcc -c -o init.o -nostdlib -nostdinc -I ../library/include -m32 init.c
ld -m elf_i386 --oformat binary -e main_init -o init -nostdlib init.o ../library/libc.o
Thanks,
-JL
Posted: Tue Jan 29, 2008 7:05 pm
by ucosty
Your code looks good so, and since you say the printing of individual letters works, it looks to me to be a problem in linking (rodata).
Posted: Tue Jan 29, 2008 7:14 pm
by piranha
Well, heres some more info that might help:
This here is my stdio.h file (which is included in init.c):
Code: Select all
extern int putch(char c);
extern int puts(char *str);
#define NULL 0
Here is how the library is built:
Code: Select all
gcc -c -o libc.o libc.c
ld libc.o -e libc_main -o libc.elf
Note: The entry libc_main isn't there. Problem?
And you may notice that I don't use the libc.elf file generated in linking. Should I?
My sys_print function:
Code: Select all
void sys_print(struct Register *regs)
{
_printf("%c", regs->ebx);
}
How could I fix a linking problem? A linker script? What would I need to do?
-JL
Posted: Tue Jan 29, 2008 7:21 pm
by ucosty
piranha wrote:Well, heres some more info that might help:
This here is my stdio.h file (which is included in init.c):
Code: Select all
extern int putch(char c);
extern int puts(char *str);
#define NULL 0
Here is how the library is built:
Code: Select all
gcc -c -o libc.o libc.c
ld libc.o -e libc_main -o libc.elf
Note: The entry libc_main isn't there. Problem?
And you may notice that I don't use the libc.elf file generated in linking. Should I?
I don't think you can because you would be mixing executable types.
piranha wrote:My sys_print function:
Code: Select all
void sys_print(struct Register *regs)
{
_printf("%c", regs->ebx);
}
How could I fix a linking problem? A linker script? What would I need to do?
-JL
I would create a linker script for you programs that would remove any ambiguity as to where you program contains data and code. I would also suggest reading up on ELF files as they are nice and flexible as well as being easy to read.
Posted: Tue Jan 29, 2008 8:17 pm
by piranha
What do I need to do in my linker script? I'm not too good at making linker scripts.
-JL
Posted: Wed Jan 30, 2008 2:13 am
by bewing
One thing I notice is that you define/call your puts function 3 different ways.
puts ("char constant");
puts (char str[256]);
puts (char *str);
I think that sometimes mixing constants in this way can cause compiler goofs. I suspect that you get a warning, at least, already. I'm not sure this is actually a problem, though.
Posted: Wed Jan 30, 2008 2:37 am
by ucosty
I checked that in VS2005 and it didn't even produce a warning. I *think* that the array length is ignored as it doesn't limit the array access bounds at all.
Re: 'Libary' problems, and syscalls.
Posted: Wed Jan 30, 2008 3:43 am
by Combuster
piranha wrote:When I call this function, nothing appears on the screen after the 'Hello' print out.
Here is the main() function:
Code: Select all
int main_init()
{
putch('H');putch('e');putch('l');putch('l');putch('o');putch('!');putch('\n');
puts("Hello, Testing. Hello World!");
}
You say you have tested it with characters, but do punctuation and special characters work as well?
Posted: Wed Jan 30, 2008 8:09 am
by Solar
Test 1:
putch('x') seems to work allright. Add a putch('x') as first statement to your puts() function to see puts() actually gets executed.
Test 2:
Check a hexdump of your binary to see if it actually contains your "Hello world" statement. If not, you're missing .rodata (as ucosty suspected).
Well ...
Posted: Wed Jan 30, 2008 11:16 am
by DeletedAccount
Hi , i also had the same problem once ... But it worked the after i replaced ur above code with something like this
Code: Select all
void put_str(char *str)
{
char *str_ptr = str;
while(*str_ptr != '\0')
{
putchar(*str_ptr);
str_ptr++;
}
}
I still do not know the reason for the glitch ... but it works this way ...
Posted: Wed Jan 30, 2008 6:45 pm
by piranha
putch('x') seems to work allright. Add a putch('x') as first statement to your puts() function to see puts() actually gets executed.
I tried that, puts() is executed.
One thing I notice is that you define/call your puts function 3 different ways.
puts ("char constant");
puts (char str[256]);
puts (char *str);
I think that sometimes mixing constants in this way can cause compiler goofs. I suspect that you get a warning, at least, already. I'm not sure this is actually a problem, though.
OK, I now have that, heres the new code:
Code: Select all
putch('H');putch('e');putch('l');putch('l');putch('o');putch('!');putch('!');putch('\n');
char hw[16];
hw[0] = 'W';
hw[1] = 'o';
hw[2] = 'r';
hw[3] = 'l';
hw[4] = 'd';
hw[5] = '\n';
put_str(hw);
I know I waste space, but it's for testing. Anyway, the output:
NOTE: Replace the star with a funny little arrow pointing to the right symbol.
Maybe the new function (the one recommended by SandeepMathew) calls putch() one too many times with a junk character at the end?
Yes, thats the problem. Actually, I need to append a \0 character.
OK, cool. It works now.
However, a const string don't (like put_str("Hello")).......can you give me tips on linker scripts? It is odd, seeing as a normal C program can use "..." but this one can't. Why is that?
-JL
Posted: Wed Jan 30, 2008 11:00 pm
by ucosty
String constants (like "Hello, world" and similar) are put in the .rodata section by GCC. Without a linker script the linker drops the section.
Here is an example linker script derived from the script on the FreeBasic barebones tutorial by combuster.
Code: Select all
OUTPUT_FORMAT("elf32-i386")
ENTRY (loader)
SECTIONS{
. = 0x00100000;
.text :{
*(.text)
}
.data ALIGN (0x1000) : {
*(.data)
[b]*(.rodata)[/b]
}
.bss : {
_sbss = .;
*(.bss)
_ebss = .;
}
}
obviously you cant just drop this in and expect it to work. You'll have to at least change the entrypoint, output format and the link address to make it work with what your OS expects.
Posted: Thu Jan 31, 2008 2:30 am
by Combuster
I copied that script from one of those other tuts out there
Posted: Thu Jan 31, 2008 9:40 am
by Solar
piranha wrote:Maybe the new function (the one recommended by SandeepMathew) calls putch() one too many times with a junk character at the end?
Yes, thats the problem. Actually, I need to append a \0 character.
A \0 character is appended automatically when you use "...". A C coder of some repute
should know that.
It is odd, seeing as a normal C program can use "..." but this one can't. Why is that?
See above - because you are missing the .rodata section (and so far, all hints that pointed in that direction).
Posted: Thu Jan 31, 2008 9:46 am
by piranha
Solar wrote:piranha wrote:Maybe the new function (the one recommended by SandeepMathew) calls putch() one too many times with a junk character at the end?
Yes, thats the problem. Actually, I need to append a \0 character.
A \0 character is appended automatically when you use "...". A C coder of some repute
should know that.
It is odd, seeing as a normal C program can use "..." but this one can't. Why is that?
See above - because you are missing the .rodata section (and so far, all hints that pointed in that direction).
Well, I said that is a post where the code
didn't use a "..." string. Plus appending a \0 character to the array I used worked.
Yes, I didn't know that ld drops the .rodata. So, now I'm a tryin' to fix that.
-JL