Why is ld complaining?

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.
NunoLava1998
Member
Member
Posts: 273
Joined: Sun Oct 09, 2016 4:38 am
Libera.chat IRC: NunoLava1998

Why is ld complaining?

Post by NunoLava1998 »

I've finally made a keyboard-usable kernel.
However, i686-elf-gcc linker mode complains about:

Code: Select all

boot.o: In function `_start':
(.text+0x6): undefined reference to `_init'
kernel.o: In function `prints':
kernel.c:(.text+0x15d): undefined reference to `strlen'
collect2.exe: error: ld returned 1 exit status
(prints is terminal_writestring renamed to prints, nothing else)

Here are the culprits that seem to be causing this:

BOOT.S:

Code: Select all

	call _init /* call our global constructors, this is in _start, also this comment doesn't exist */
TTY.C (It says it's in kernel.c but it's actually included by kernel.c but the linker doesn't care since GCC just adds the code anyway):

Code: Select all

void prints(const char* data) {
	terminal_write(data, strlen(data)); /* complaining here on "strlen", i have a string.h included which is the same one from meaty skeleton without  #INCLUDE cdefs*/ 
}
Developing TRIODIUM OS. Or call it Dixium if you want. It doesn't matter.

https://github.com/NunoLava1998/DixiumOS
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Why is ld complaining?

Post by iansjack »

ld is complaining for exactly the reasons given in the error messages.

On a higher level, it is complaining because you don't know how to program in C.
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: Why is ld complaining?

Post by Ycep »

Can you show us at least little bit more code?
If you are forcing us to judge why is ld complaining you may need to give us some more code.
NunoLava1998
Member
Member
Posts: 273
Joined: Sun Oct 09, 2016 4:38 am
Libera.chat IRC: NunoLava1998

Re: Why is ld complaining?

Post by NunoLava1998 »

iansjack wrote:ld is complaining for exactly the reasons given in the error messages.

On a higher level, it is complaining because you don't know how to program in C.
Except the 2 are part of boot.S which i NEVER modified or tty.c which i never modified except for renaming terminal_writestring to prints.
Developing TRIODIUM OS. Or call it Dixium if you want. It doesn't matter.

https://github.com/NunoLava1998/DixiumOS
NunoLava1998
Member
Member
Posts: 273
Joined: Sun Oct 09, 2016 4:38 am
Libera.chat IRC: NunoLava1998

Re: Why is ld complaining?

Post by NunoLava1998 »

Lukand wrote:Can you show us at least little bit more code?
If you are forcing us to judge why is ld complaining you may need to give us some more code.
a part of boot.S (unmodified):

Code: Select all

# The kernel entry point.
.section .text
.global _start
.type _start, @function
_start:
	movl $stack_top, %esp

	# Call the global constructors.
	call _init

	# Transfer control to the main kernel.
	call kernel_main

	# Hang if kernel_main unexpectedly returns.
	cli
1:	hlt
	jmp 1b
.size _start, . - _start
tty.c (vga.h is the enums and terminal_init and the other basic things, the same vga.h as in Meaty Skeleton basically):

Code: Select all

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "string.h"
#include "vga.h"
 
static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25;
static uint16_t* const VGA_MEMORY = (uint16_t*) 0xB8000;
 
static size_t terminal_row;
static size_t terminal_column;
static uint8_t terminal_color;
static uint16_t* terminal_buffer;
 
void terminal_initialize(void) {
	terminal_row = 0;
	terminal_column = 0;
	terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
	terminal_buffer = VGA_MEMORY;
	for (size_t y = 0; y < VGA_HEIGHT; y++) {
		for (size_t x = 0; x < VGA_WIDTH; x++) {
			const size_t index = y * VGA_WIDTH + x;
			terminal_buffer[index] = vga_entry(' ', terminal_color);
		}
	}
}
 
void terminal_setcolor(uint8_t color) {
	terminal_color = color;
}
 
void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) {
	const size_t index = y * VGA_WIDTH + x;
	terminal_buffer[index] = vga_entry(c, color);
}
 
void terminal_putchar(char c) {
	unsigned char uc = c;
	terminal_putentryat(uc, terminal_color, terminal_column, terminal_row);
	if (++terminal_column == VGA_WIDTH) {
		terminal_column = 0;
		if (++terminal_row == VGA_HEIGHT)
			terminal_row = 0;
	}
}
 
void terminal_write(const char* data, size_t size) {
	for (size_t i = 0; i < size; i++)
		terminal_putchar(data[i]);
}
 
void prints(const char* data) {
	terminal_write(data, strlen(data));
}
vga.h (if you are curious):

Code: Select all

#ifndef ARCH_I386_VGA_H
#define ARCH_I386_VGA_H
 
#include <stdint.h>
 
enum vga_color {
	VGA_COLOR_BLACK = 0,
	VGA_COLOR_BLUE = 1,
	VGA_COLOR_GREEN = 2,
	VGA_COLOR_CYAN = 3,
	VGA_COLOR_RED = 4,
	VGA_COLOR_MAGENTA = 5,
	VGA_COLOR_BROWN = 6,
	VGA_COLOR_LIGHT_GREY = 7,
	VGA_COLOR_DARK_GREY = 8,
	VGA_COLOR_LIGHT_BLUE = 9,
	VGA_COLOR_LIGHT_GREEN = 10,
	VGA_COLOR_LIGHT_CYAN = 11,
	VGA_COLOR_LIGHT_RED = 12,
	VGA_COLOR_LIGHT_MAGENTA = 13,
	VGA_COLOR_LIGHT_BROWN = 14,
	VGA_COLOR_WHITE = 15,
};
 
static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
	return fg | bg << 4;
}
 
static inline uint16_t vga_entry(unsigned char uc, uint8_t color) {
	return (uint16_t) uc | (uint16_t) color << 8;
}
 
#endif
Developing TRIODIUM OS. Or call it Dixium if you want. It doesn't matter.

https://github.com/NunoLava1998/DixiumOS
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Why is ld complaining?

Post by iansjack »

NunoLava1998 wrote:
iansjack wrote:ld is complaining for exactly the reasons given in the error messages.

On a higher level, it is complaining because you don't know how to program in C.
Except the 2 are part of boot.S which i NEVER modified or tty.c which i never modified except for renaming terminal_writestring to prints.
No, they are not.
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: Why is ld complaining?

Post by Ycep »

If you keep trying to hide your OS that could be written for 5 minutes, for 2 mins if you copy paste meaty skeleton as you did, there's few things I could suspect:
  • You did not included apporiate header with prints() definition.
  • You did not declared prints() in any header at all.
Last edited by Ycep on Wed Nov 16, 2016 3:21 pm, edited 1 time in total.
NunoLava1998
Member
Member
Posts: 273
Joined: Sun Oct 09, 2016 4:38 am
Libera.chat IRC: NunoLava1998

Re: Why is ld complaining?

Post by NunoLava1998 »

Lukand wrote:If you keep trying to hide your OS that could be written for 5 minutes, for 2 mins if you copy paste meaty skeleton as you did, there's few things I could suspect:
  • You did not included apporiate header with prints() definition.
  • You did not defined prints() in any header at all.
I defined it in tty.c. It is valid, it is literally tty.c from meaty skeleton with

However, GCC compiled fine with -w. I use -w beacuse some errors in my code are intended and if they aren't GCC will just fix it anyway

terminal_writestring:

Code: Select all

void terminal_writestring(const char* data) {
	terminal_write(data, strlen(data));
}
prints:

Code: Select all

void prints(const char* data) {
	terminal_write(data, strlen(data));
}
Developing TRIODIUM OS. Or call it Dixium if you want. It doesn't matter.

https://github.com/NunoLava1998/DixiumOS
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: Why is ld complaining?

Post by Schol-R-LEA »

I think we need to see the code for init and strlen, the header file they are declared in, and your Makefile and linker script.

Or, you know, you could give us a link to your cloud repo. The one you probably don't have yet because you never listen to advice. Go, drop everything, head over to GitHub or CloudForge and make one right now, and get your code under version control before you do anything else. You are sitting on a bomb that is about to go off and you don't even realize it.

Seriously, you really are the fool we have been taking you for if you don't do this right away.

Speaking of which:
NunoLava1998 wrote:

Code: Select all

enum vga_color {
	VGA_COLOR_BLACK = 0,
	VGA_COLOR_BLUE = 1,
	VGA_COLOR_GREEN = 2,
	VGA_COLOR_CYAN = 3,
	VGA_COLOR_RED = 4,
	VGA_COLOR_MAGENTA = 5,
	VGA_COLOR_BROWN = 6,
	VGA_COLOR_LIGHT_GREY = 7,
	VGA_COLOR_DARK_GREY = 8,
	VGA_COLOR_LIGHT_BLUE = 9,
	VGA_COLOR_LIGHT_GREEN = 10,
	VGA_COLOR_LIGHT_CYAN = 11,
	VGA_COLOR_LIGHT_RED = 12,
	VGA_COLOR_LIGHT_MAGENTA = 13,
	VGA_COLOR_LIGHT_BROWN = 14,
	VGA_COLOR_WHITE = 15,
};
:roll: You do know that enum will automagically set the values in a fixed order starting at zero for you if you don't set an explicit value, right? That's the whole point of enumerations. Change it to this and it will actually be more readable to most C programmers:

Code: Select all

enum vga_color {
	VGA_COLOR_BLACK,
	VGA_COLOR_BLUE,
	VGA_COLOR_GREEN,
	VGA_COLOR_CYAN,
	VGA_COLOR_RED,
	VGA_COLOR_MAGENTA,
	VGA_COLOR_BROWN,
	VGA_COLOR_LIGHT_GREY,
	VGA_COLOR_DARK_GREY,
	VGA_COLOR_LIGHT_BLUE,
	VGA_COLOR_LIGHT_GREEN,
	VGA_COLOR_LIGHT_CYAN ,
	VGA_COLOR_LIGHT_RED,
	VGA_COLOR_LIGHT_MAGENTA,
	VGA_COLOR_LIGHT_BROWN,
	VGA_COLOR_WHITE
};
As I said in the other thread, the values of an enumeration are more or less a side effect of how they are implemented. Using them for those values is sort of off-brand, but permissible in C, but the whole idea of an enum is to define the order of the constants, not the specific values. If the order doesn't matter, use const or #define for general constants. In this case, it really isn't, so using an enumeration for it is a Bad Idea. This is really a better solution all around:

Code: Select all

const uint8_t VGA_COLOR_BLACK = 0,
              VGA_COLOR_BLUE = 1,
              VGA_COLOR_GREEN = 2,
              VGA_COLOR_CYAN = 3,
              VGA_COLOR_RED = 4,
              VGA_COLOR_MAGENTA = 5,
              VGA_COLOR_BROWN = 6,
              VGA_COLOR_LIGHT_GREY = 7,
              VGA_COLOR_DARK_GREY = 8,
              VGA_COLOR_LIGHT_BLUE = 9,
              VGA_COLOR_LIGHT_GREEN = 10,
              VGA_COLOR_LIGHT_CYAN = 11,
              VGA_COLOR_LIGHT_RED = 12,
              VGA_COLOR_LIGHT_MAGENTA = 13,
              VGA_COLOR_LIGHT_BROWN = 14,
              VGA_COLOR_WHITE = 15;
I won't bother mentioning that this isn't a good way to do that anyway, because VGA palettes aren't fixed, but whatever.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: Why is ld complaining?

Post by Schol-R-LEA »

NunoLava1998 wrote:However, GCC compiled fine with -w. I use -w beacuse some errors in my code are intended and if they aren't GCC will just fix it anyway
It will? News to me. Today I learned that GCC has a Do What I Mean feature, just perfect! I certainly hope it is better than the last DWIM method I heard about...
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: Why is ld complaining?

Post by Love4Boobies »

Generally speaking, I actually find grouping related constants into enumerated types more elegant because (a) they're not meant to be objects (which const int's are), and (b) the type itself can be used for documentation purposes. Consider the following example:

Code: Select all

enum somename {
    FOO = 0xDEADBEEF,
    BAR = 0xC0DECAFE
};

void foo(const enum somename);
You can tell the set of values that were meant to be passed to foo just by looking at its prototype.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
glauxosdever
Member
Member
Posts: 501
Joined: Wed Jun 17, 2015 9:40 am
Libera.chat IRC: glauxosdever
Location: Athens, Greece

Re: Why is ld complaining?

Post by glauxosdever »

Hi,


GCC will not fix errors automagically if invoked with the -w option. It will just refrain from reporting warnings (and not errors). Errors and warnings will continue to exist, although the latter won't be reported.

Part of my complaint is with the toolchain. A beginner-friendly toolchain would enable all useful warnings by default. If an option to suppress them was really needed, the manual would explicitly state that warnings are simply suppressed and not fixed (even if it seems obvious to expert programmers). So the only advice I can give (along with learning C) is to always compile with -Wall -Wextra and without -w.


Regards,
glauxosdever
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: Why is ld complaining?

Post by Schol-R-LEA »

Love4Boobies wrote:Generally speaking, I actually find grouping related constants into enumerated types more elegant because (a) they're not meant to be objects (which const int's are), and (b) the type itself can be used for documentation purposes. Consider the following example:

Code: Select all

enum somename {
    FOO = 0xDEADBEEF,
    BAR = 0xC0DECAFE
};

void foo(const enum somename);
You can tell the set of values that were meant to be passed to foo just by looking at its prototype.
OK, that's a fair point, but only to a degree. What you really would want is either a discrete-valued type (which C doesn't have a general form of, though enums can be seen as a special case of them and are often used for one) or a hashtable/dictionary type (which would normally be a library type in C, and would be overkill in this case anyway). While enums are a sub-category of discrete-valued types, they probably shouldn't be the used as a replacement for a more general discrete-valued type mechanism.

For larger sets of values, I would actually use a lookup table, and if I absolutely needed named constants for the indices, I would define the enum for those. It would be a little slower, since it would require an indirection, but far, far more flexible.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
NunoLava1998
Member
Member
Posts: 273
Joined: Sun Oct 09, 2016 4:38 am
Libera.chat IRC: NunoLava1998

Re: Why is ld complaining?

Post by NunoLava1998 »

Schol-R-LEA wrote:I think we need to see the code for init and strlen, the header file they are declared in, and your Makefile and linker script.

Or, you know, you could give us a link to your cloud repo. The one you probably don't have yet because you never listen to advice. Go, drop everything, head over to GitHub or CloudForge and make one right now, and get your code under version control before you do anything else. You are sitting on a bomb that is about to go off and you don't even realize it.

Seriously, you really are the fool we have been taking you for if you don't do this right away.

Speaking of which:
NunoLava1998 wrote:

Code: Select all

enum vga_color {
	VGA_COLOR_BLACK = 0,
	VGA_COLOR_BLUE = 1,
	VGA_COLOR_GREEN = 2,
	VGA_COLOR_CYAN = 3,
	VGA_COLOR_RED = 4,
	VGA_COLOR_MAGENTA = 5,
	VGA_COLOR_BROWN = 6,
	VGA_COLOR_LIGHT_GREY = 7,
	VGA_COLOR_DARK_GREY = 8,
	VGA_COLOR_LIGHT_BLUE = 9,
	VGA_COLOR_LIGHT_GREEN = 10,
	VGA_COLOR_LIGHT_CYAN = 11,
	VGA_COLOR_LIGHT_RED = 12,
	VGA_COLOR_LIGHT_MAGENTA = 13,
	VGA_COLOR_LIGHT_BROWN = 14,
	VGA_COLOR_WHITE = 15,
};
:roll: You do know that enum will automagically set the values in a fixed order starting at zero for you if you don't set an explicit value, right? That's the whole point of enumerations. Change it to this and it will actually be more readable to most C programmers:

Code: Select all

enum vga_color {
	VGA_COLOR_BLACK,
	VGA_COLOR_BLUE,
	VGA_COLOR_GREEN,
	VGA_COLOR_CYAN,
	VGA_COLOR_RED,
	VGA_COLOR_MAGENTA,
	VGA_COLOR_BROWN,
	VGA_COLOR_LIGHT_GREY,
	VGA_COLOR_DARK_GREY,
	VGA_COLOR_LIGHT_BLUE,
	VGA_COLOR_LIGHT_GREEN,
	VGA_COLOR_LIGHT_CYAN ,
	VGA_COLOR_LIGHT_RED,
	VGA_COLOR_LIGHT_MAGENTA,
	VGA_COLOR_LIGHT_BROWN,
	VGA_COLOR_WHITE
};
As I said in the other thread, the values of an enumeration are more or less a side effect of how they are implemented. Using them for those values is sort of off-brand, but permissible in C, but the whole idea of an enum is to define the order of the constants, not the specific values. If the order doesn't matter, use const or #define for general constants. In this case, it really isn't, so using an enumeration for it is a Bad Idea. This is really a better solution all around:

Code: Select all

const uint8_t VGA_COLOR_BLACK = 0,
              VGA_COLOR_BLUE = 1,
              VGA_COLOR_GREEN = 2,
              VGA_COLOR_CYAN = 3,
              VGA_COLOR_RED = 4,
              VGA_COLOR_MAGENTA = 5,
              VGA_COLOR_BROWN = 6,
              VGA_COLOR_LIGHT_GREY = 7,
              VGA_COLOR_DARK_GREY = 8,
              VGA_COLOR_LIGHT_BLUE = 9,
              VGA_COLOR_LIGHT_GREEN = 10,
              VGA_COLOR_LIGHT_CYAN = 11,
              VGA_COLOR_LIGHT_RED = 12,
              VGA_COLOR_LIGHT_MAGENTA = 13,
              VGA_COLOR_LIGHT_BROWN = 14,
              VGA_COLOR_WHITE = 15;
I won't bother mentioning that this isn't a good way to do that anyway, because VGA palettes aren't fixed, but whatever.
"
Or, you know, you could give us a link to your cloud repo. The one you probably don't have yet because you never listen to advice. Go, drop everything, head over to GitHub or CloudForge and make one right now, and get your code under version control before you do anything else. You are sitting on a bomb that is about to go off and you don't even realize it. "

https://github.com/NunoLava1998/dixium
the ironic thing is it made it like yesterday

makefile:
i'm running windows and i'm using the compiler from max, basically just

Code: Select all

i686-elf-as boot.s -o boot.o
i686-elf-gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra -w
i686-elf-gcc -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc REM failure right here, REM is the same as # in Assembly or /* */ in C, but in Batch. You can put REM after commands.
linker script: the same one as in bare bones and meaty skeleton

_init:

Code: Select all

call _init
in boot.S is the closest thing i can find
strlen: i have no idea
Hi,


GCC will not fix errors automagically if invoked with the -w option. It will just refrain from reporting warnings (and not errors). Errors and warnings will continue to exist, although the latter won't be reported.
I know
Developing TRIODIUM OS. Or call it Dixium if you want. It doesn't matter.

https://github.com/NunoLava1998/DixiumOS
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Why is ld complaining?

Post by iansjack »

So, like I said a while ago, you haven't defined _init or strlen, which is precisely what the linker is telling you.

You don't know what you are doing.You can't read error messages. You are wasting your time. You are wasting the time of people here.
Post Reply