Page 1 of 1

I've got the dreaded 'undefined reference to 'memcpy'' error

Posted: Tue Sep 04, 2007 6:47 pm
by vhg119
I've done a search for this and found many people with the same problem. However, I was unable to find the solution.

My error appeared after I declared a large array. Commenting out the array got rid of the error. But... I'm gonna need that array.

My CFLAGS are :
CFLAGS = -Wall -O -floop-optimize2 -nostdinc -I include -ffreestanding -c

I've tried implementing my own memcpy function to no avail. LD still complains.

Has anyone who had this error before been successful in fixing it?

LD 2.17.50, gcc v4.1.2 on Ubuntu feisty.... if it matters.

Vince

Posted: Tue Sep 04, 2007 6:54 pm
by Pyrofan1
i don't have the answer to your question, but changing CFLAGS to look like that is a bad idea

Posted: Tue Sep 04, 2007 6:58 pm
by vhg119
Pyrofan1 wrote:i don't have the answer to your question, but changing CFLAGS to look like that is a bad idea
Which part of it? My CFLAGS education is lacking. Any recommendations are greatly appreciated.

Posted: Tue Sep 04, 2007 7:03 pm
by frank
Have you tried something like?

Code: Select all

void *memcpy( void *dest, const void *src, DWORD length )
{
    __asm volatile( intel(
            "cld\n\t"
            "rep  movsb" )
            : "=S" ( length ), "=D" ( length ), "=c" ( length )
            : "S" ( src ), "D" ( dest ), "c" ( length )
            : "memory" );

    return( dest );

} // end memcpy
EDIT: My CFLAGS and CPPFLAGS (not standard name, I know) looks like this for comparison

Code: Select all

CFLAGS = $(OPTIM) -c $(WARNINGS) -Wall -Wextra -fno-builtin -nostdlib -ffreestanding $(INCLUDEDIR)

CPPFLAGS = $(OPTIM) -c $(WARNINGS) -fno-builtin -nostdlib $(INCLUDEDIR) -fno-exceptions -fno-rtti

Posted: Tue Sep 04, 2007 7:32 pm
by Pyrofan1
Which part of it? My CFLAGS education is lacking. Any recommendations are greatly appreciated.
well, unless i'm mistaken CFLAGS is the compile options for the whole system so the next time you attempt to compile a program that is distributed as code the compiler will apply those options and it won't work.

Posted: Tue Sep 04, 2007 8:23 pm
by vhg119
Pyrofan1 wrote:
Which part of it? My CFLAGS education is lacking. Any recommendations are greatly appreciated.
well, unless i'm mistaken CFLAGS is the compile options for the whole system so the next time you attempt to compile a program that is distributed as code the compiler will apply those options and it won't work.
I'm sorry. I have no idea what you're saying.

CFLAGS is the name of the variable in my Makefile which contain my gcc compile parameters.

I've read a lot of documentation but I haven't really learned what parameters I should use. The man pages said I should use -ffreestanding and it makes sense to use -nostdlib and -fno-builtin since this is a kernel.

But even after those flags, gcc still attempts to reference memcpy.

Posted: Tue Sep 04, 2007 8:30 pm
by vhg119
frank wrote:Have you tried something like?

Code: Select all

void *memcpy( void *dest, const void *src, DWORD length )
{
    __asm volatile( intel(
            "cld\n\t"
            "rep  movsb" )
            : "=S" ( length ), "=D" ( length ), "=c" ( length )
            : "S" ( src ), "D" ( dest ), "c" ( length )
            : "memory" );

    return( dest );

} // end memcpy
EDIT: My CFLAGS and CPPFLAGS (not standard name, I know) looks like this for comparison

Code: Select all

CFLAGS = $(OPTIM) -c $(WARNINGS) -Wall -Wextra -fno-builtin -nostdlib -ffreestanding $(INCLUDEDIR)

CPPFLAGS = $(OPTIM) -c $(WARNINGS) -fno-builtin -nostdlib $(INCLUDEDIR) -fno-exceptions -fno-rtti
Thanks for your help...

I get errors when trying to compile the code you recommended.

Code: Select all

error: expected string literal before ‘intel’

Posted: Tue Sep 04, 2007 9:35 pm
by jerryleecooper
vhg119 wrote:
I get errors when trying to compile the code you recommended.

Code: Select all

error: expected string literal before ‘intel’
Simple, remove "intel" and its parenthesis, or simpler, add

Code: Select all

#define intel(x) (x)
since it seems something logical to do, but I may be wrong.

Posted: Wed Sep 05, 2007 12:56 am
by raistlinthewiz
i started developing my own kernel with 3.x series and when i ported to gcc 4 series, i hit similar problems. i fixed them by changing my array declarations.

Posted: Wed Sep 05, 2007 2:09 am
by JamesM
Jerryleecooper: I don't think that macro definition will work, the poster was using the intel directive to force GAS into intel-syntax mode. Obviously either (a) this is not supported on the OP's compiler or (b) there is some syntax error somewhere.

What exactly are the errors you're seeing?

And pyrofan1: He's not changing the system-wide env variable 'CFLAGS', he's setting it locally in his makefile. Thats what everyone does :P

JamesM

Posted: Wed Sep 05, 2007 9:53 am
by vhg119
raistlinthewiz wrote:i started developing my own kernel with 3.x series and when i ported to gcc 4 series, i hit similar problems. i fixed them by changing my array declarations.
Hi, in what way did you change your array declaration?
JamesM wrote:
What exactly are the errors you're seeing?
James, I'm following a part of this tutorial: http://en.skelix.org/skelixos/tutorial05.php

This is the offending code:

Code: Select all

void do_kb(void)
{
        void (*key_way[0x80])(void) = {
		unp, unp, pln, pln, pln, pln, pln, pln,
		pln, pln, pln, pln, pln, pln, pln, pln,
		pln, pln, pln, pln, pln, pln, pln, pln,
		pln, pln, pln, pln, pln, ctl, pln, pln,
		pln, pln, pln, pln, pln, pln, pln, pln,
		pln, pln, shf, pln, pln, pln, pln, pln,
		pln, pln, pln, pln, pln, pln, shf, pln,
		alt, pln, unp, fun, fun, fun, fun, fun,
		fun, fun, fun, fun, fun, unp, unp, unp,
		unp, unp, unp, unp, unp, unp, unp, unp,
		unp, unp, unp, unp, unp, unp, unp, fun,
		fun, unp, unp, unp, unp, unp, unp, unp,
		unp, unp, unp, unp, unp, unp, unp, unp,
		unp, unp, unp, unp, unp, unp, unp, unp,
		unp, unp, unp, unp, unp, unp, unp, unp,
		unp, unp, unp, unp, unp, unp, unp, unp,
	};

...

}
It's just an array of function pointers.

This is the error I get when I link:

Code: Select all

ld -T link.ld start.o main.o gdt.o tss.o idt.o isr.o irq.o timer.o video.o -Map kernel.map -o kernel.bin 
irq.o: In function `do_kb':
irq.c:(.text+0x51): undefined reference to `memcpy'
make[2]: *** [kernel] Error 1

Posted: Wed Sep 05, 2007 10:56 am
by JamesM
can you objdump -d irq.o please? I want to see why it's calling memcpy.

Code: Select all

objdump -d irq.o

Posted: Wed Sep 05, 2007 11:10 am
by Combuster
You have three options:
1: declare the entire array globally
2: declare the array contents globally, then use a pointer to that.
3: implement memcpy. (you can grab it from a libc if you don't want to write it manually)

Posted: Wed Sep 05, 2007 11:20 am
by vhg119
Combuster wrote:You have three options:
1: declare the entire array globally
2: declare the array contents globally, then use a pointer to that.
3: implement memcpy. (you can grab it from a libc if you don't want to write it manually)
Thanks Combuster, I declared the array as static. That got rid of the error.
JamesM wrote:can you objdump -d irq.o please? I want to see why it's calling memcpy.

Code: Select all

objdump -d irq.o
here ya go..
irq.o: file format elf32-i386

Disassembly of section .text:

00000000 <ctl>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 80 35 00 00 00 00 01 xorb $0x1,0x0
a: 5d pop %ebp
b: c3 ret

0000000c <alt>:
c: 55 push %ebp
d: 89 e5 mov %esp,%ebp
f: 80 35 00 00 00 00 01 xorb $0x1,0x0
16: 5d pop %ebp
17: c3 ret

00000018 <shf>:
18: 55 push %ebp
19: 89 e5 mov %esp,%ebp
1b: 80 35 00 00 00 00 01 xorb $0x1,0x0
22: 5d pop %ebp
23: c3 ret

00000024 <fun>:
24: 55 push %ebp
25: 89 e5 mov %esp,%ebp
27: 5d pop %ebp
28: c3 ret

00000029 <unp>:
29: 55 push %ebp
2a: 89 e5 mov %esp,%ebp
2c: 5d pop %ebp
2d: c3 ret

0000002e <do_kb>:
2e: 55 push %ebp
2f: 89 e5 mov %esp,%ebp
31: 81 ec 18 02 00 00 sub $0x218,%esp
37: 8d 85 00 fe ff ff lea 0xfffffe00(%ebp),%eax
3d: c7 44 24 08 00 02 00 movl $0x200,0x8(%esp)
44: 00
45: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
4c: 00
4d: 89 04 24 mov %eax,(%esp)
50: e8 fc ff ff ff call 51 <do_kb+0x23>
55: ba 60 00 00 00 mov $0x60,%edx
5a: ec in (%dx),%al
5b: a2 00 00 00 00 mov %al,0x0
60: 83 e0 7f and $0x7f,%eax
63: ff 94 85 00 fe ff ff call *0xfffffe00(%ebp,%eax,4)
6a: ba 61 00 00 00 mov $0x61,%edx
6f: ec in (%dx),%al
70: 0f b6 c0 movzbl %al,%eax
73: 89 c1 mov %eax,%ecx
75: 80 c9 80 or $0x80,%cl
78: ee out %al,(%dx)
79: 83 e0 7f and $0x7f,%eax
7c: ee out %al,(%dx)
7d: c9 leave
7e: c3 ret

0000007f <pln>:
7f: 55 push %ebp
80: 89 e5 mov %esp,%ebp
82: 83 ec 08 sub $0x8,%esp
85: e8 fc ff ff ff call 86 <pln+0x7>
8a: c7 04 24 00 00 00 00 movl $0x0,(%esp)
91: e8 fc ff ff ff call 92 <pln+0x13>
96: c9 leave
97: c3 ret

00000098 <do_timer>:
98: 55 push %ebp
99: 89 e5 mov %esp,%ebp
9b: 83 ec 28 sub $0x28,%esp
9e: a1 00 00 00 00 mov 0x0,%eax
a3: 83 c0 01 add $0x1,%eax
a6: a3 00 00 00 00 mov %eax,0x0
ab: ba 00 00 00 00 mov $0x0,%edx
b0: 83 f8 13 cmp $0x13,%eax
b3: 7e 2d jle e2 <do_timer+0x4a>
b5: ba 01 00 00 00 mov $0x1,%edx
ba: 83 f8 27 cmp $0x27,%eax
bd: 7e 23 jle e2 <do_timer+0x4a>
bf: ba 02 00 00 00 mov $0x2,%edx
c4: 83 f8 3b cmp $0x3b,%eax
c7: 7e 19 jle e2 <do_timer+0x4a>
c9: ba 03 00 00 00 mov $0x3,%edx
ce: 83 f8 4f cmp $0x4f,%eax
d1: 7e 0f jle e2 <do_timer+0x4a>
d3: c7 05 00 00 00 00 00 movl $0x0,0x0
da: 00 00 00
dd: ba 00 00 00 00 mov $0x0,%edx
e2: c6 45 fc 2d movb $0x2d,0xfffffffc(%ebp)
e6: c6 45 fd 5c movb $0x5c,0xfffffffd(%ebp)
ea: c6 45 fe 7c movb $0x7c,0xfffffffe(%ebp)
ee: c6 45 ff 2f movb $0x2f,0xffffffff(%ebp)
f2: 0f b6 44 15 fc movzbl 0xfffffffc(%ebp,%edx,1),%eax
f7: 89 44 24 10 mov %eax,0x10(%esp)
fb: c7 44 24 0c 0f 00 00 movl $0xf,0xc(%esp)
102: 00
103: c7 44 24 08 00 00 00 movl $0x0,0x8(%esp)
10a: 00
10b: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
112: 00
113: c7 04 24 00 00 00 00 movl $0x0,(%esp)
11a: e8 fc ff ff ff call 11b <do_timer+0x83>
11f: c9 leave
120: c3 ret

00000121 <irq_handler>:
121: 55 push %ebp
122: 89 e5 mov %esp,%ebp
124: 56 push %esi
125: 53 push %ebx
126: 83 ec 50 sub $0x50,%esp
129: 8b 5d 08 mov 0x8(%ebp),%ebx
12c: 8b 73 30 mov 0x30(%ebx),%esi
12f: 83 ee 20 sub $0x20,%esi
132: 75 0a jne 13e <irq_handler+0x1d>
134: e8 fc ff ff ff call 135 <irq_handler+0x14>
139: e9 83 00 00 00 jmp 1c1 <irq_handler+0xa0>
13e: 66 90 xchg %ax,%ax
140: e8 fc ff ff ff call 141 <irq_handler+0x20>
145: c7 45 b8 0c 00 00 00 movl $0xc,0xffffffb8(%ebp)
14c: c7 45 bc 19 00 00 00 movl $0x19,0xffffffbc(%ebp)
153: c7 45 c0 29 00 00 00 movl $0x29,0xffffffc0(%ebp)
15a: c7 45 c4 2e 00 00 00 movl $0x2e,0xffffffc4(%ebp)
161: c7 45 c8 3a 00 00 00 movl $0x3a,0xffffffc8(%ebp)
168: c7 45 cc 46 00 00 00 movl $0x46,0xffffffcc(%ebp)
16f: c7 45 d0 52 00 00 00 movl $0x52,0xffffffd0(%ebp)
176: c7 45 d4 60 00 00 00 movl $0x60,0xffffffd4(%ebp)
17d: c7 45 d8 6c 00 00 00 movl $0x6c,0xffffffd8(%ebp)
184: c7 45 dc 7e 00 00 00 movl $0x7e,0xffffffdc(%ebp)
18b: c7 45 e0 83 00 00 00 movl $0x83,0xffffffe0(%ebp)
192: c7 45 e4 89 00 00 00 movl $0x89,0xffffffe4(%ebp)
199: c7 45 e8 8f 00 00 00 movl $0x8f,0xffffffe8(%ebp)
1a0: c7 45 ec a1 00 00 00 movl $0xa1,0xffffffec(%ebp)
1a7: c7 45 f0 a7 00 00 00 movl $0xa7,0xfffffff0(%ebp)
1ae: c7 45 f4 b4 00 00 00 movl $0xb4,0xfffffff4(%ebp)
1b5: 8b 44 b5 b8 mov 0xffffffb8(%ebp,%esi,4),%eax
1b9: 89 04 24 mov %eax,(%esp)
1bc: e8 fc ff ff ff call 1bd <irq_handler+0x9c>
1c1: 83 7b 30 27 cmpl $0x27,0x30(%ebx)
1c5: 76 0b jbe 1d2 <irq_handler+0xb1>
1c7: b8 20 00 00 00 mov $0x20,%eax
1cc: ba a0 00 00 00 mov $0xa0,%edx
1d1: ee out %al,(%dx)
1d2: b8 20 00 00 00 mov $0x20,%eax
1d7: ba 20 00 00 00 mov $0x20,%edx
1dc: ee out %al,(%dx)
1dd: 83 c4 50 add $0x50,%esp
1e0: 5b pop %ebx
1e1: 5e pop %esi
1e2: 5d pop %ebp
1e3: c3 ret

Posted: Wed Sep 05, 2007 6:21 pm
by frank
vhg119 wrote: I get errors when trying to compile the code you recommended.

Code: Select all

error: expected string literal before ‘intel’
Oops I'm sorry, I really should read over the things I post. Yes I use intel as a macro to force intel syntax. Here it is.

Code: Select all

#define intel(x) ".intel_syntax noprefix\n\t" x "\n\t.att_syntax prefix"
:oops: