LD Linking Problems... (2 of them...)

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.
astrocrep

LD Linking Problems... (2 of them...)

Post by astrocrep »

Ok heres the thing... I am using djgpp under xp pro... and I am running a batch file to compile my os

Code: Select all

@echo off
echo Cleaning Up...
cd build
del *.o
del *.out
del *.bin
cd ..\source
del *.o
del *.out
del *.bin
cd ..

echo Entering Source...
cd source

echo Compiling Files...
set copt=-ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions

nasm -f aout start.asm -o start.o
nasm -f aout misccode.asm -o misccode.o
nasm -f aout interrupts.asm -o interrupts.o

gxx -c %copt% *.cpp

move *.o ..\build
set copt=

echo Linking Objects
cd ..\build
ld -T kernel.ld -o kernel.bin *.o

echo Copying Kernel!
copy kernel.bin ..\..\Image
cd ..
Problem 1:

Originally instead of the wildcards I had each file named out... however the line that executes LD become longer than dos could support and as such linking became impossible. So I am now using wildcards... will this matter if the start procedure isn't at the head of the file? Or should I name the file with the start code 00start.o ?? This way it would technically be the first file?

Problem 2:

I am mixing C and Assembler code and having a nightmare... Inside C, calling an asm function is fine... however in asm calling an existing c function is nothing put troubles... gxx compiles fine and gives no errors... but linking goes crazy saying :

Code: Select all

interrupts.o(.text+0x12): undefined reference to `_int_00'
(1 error for each of my interrupt functions )
panic.o(.text+0xc):panic.cpp: undefined reference to `__Z5int00v'
(1 error for each of my interrupt functions )
It compiles fine no errors or anything

Heres a sample from interrupts.asm

Code: Select all

[extern _int_00]
[global _int00]
_int00:
     pusha
     push ds
     push es
     push fs
     push gs
     mov eax,0x10    ; Data segment
     mov ds,eax
     mov es,eax
     cld
     call _int_00    ; Divide by Zero #DE
     pop gs
     pop fs
     pop es
     pop ds
     popa
     iret
and heres some from panic.cpp

Code: Select all

void int_00(void)
{
   printf("Divide By Zero Error");
}
and on the reverse side of the spectrum...
The CPP Code includess a header file which help refrence all of the assembler code:

Code: Select all

extern void int00(void);
I am soo lost by whats going on here... as you can probably tell... thanks for any help.

Rich P.

P.S. If anyone had any good examples or TUTs for making makefiles compatible with djgpp please let me know. Thanks again.
astrocrep

Re:LD Linking Problems... (2 of them...)

Post by astrocrep »

Update on problem 2,

In my header file that declares the assembler based interrupt handlers I added

Code: Select all

extern "C" {  all my functions... }
And it got rid of half my errors...

The ones that remain are genereated from the linker not being able to "find" the C++ Functions from ASM...
"undefined refrence"

Thanks for the help!

Rich P.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:LD Linking Problems... (2 of them...)

Post by Candy »

astrocrep wrote: Ok heres the thing... I am using djgpp under xp pro... and I am running a batch file to compile my os
what are "compile my os", "winxp" and "batch file" doing in the same post? Make has even been ported to windows-ish stuff, along with a decent shell, so you might want to consider that
Problem 1:

Originally instead of the wildcards I had each file named out... however the line that executes LD become longer than dos could support and as such linking became impossible. So I am now using wildcards... will this matter if the start procedure isn't at the head of the file? Or should I name the file with the start code 00start.o ?? This way it would technically be the first file?
You could do that, but you can also start using recursive linking. That also reduces the length of the compile line. Also, in a linker script you can list all the object files so you don't have to specify them on the command line anymore. As a final solution for a really big project you could start thinking about making it into multiple subdirectories and using something similar to recursive makefiles.
Problem 2:

I am mixing C and Assembler code and having a nightmare... Inside C, calling an asm function is fine... however in asm calling an existing c function is nothing put troubles... gxx compiles fine and gives no errors... but linking goes crazy saying :

Code: Select all

interrupts.o(.text+0x12): undefined reference to `_int_00'
(1 error for each of my interrupt functions )
panic.o(.text+0xc):panic.cpp: undefined reference to `__Z5int00v'
(1 error for each of my interrupt functions )
You are mixing C and assembler, and you are compiling with a C++ compiler. Because you indicate it's c++ code, the c++ name mangling is also done. Try using:

Code: Select all

extern "C" {
   some C function definition or declaration
}
in your code to explicitly use C linkage, or rename it to .c and use that, or change your assembly code to conform to the naming of the c++-compiled code (your assembly function becomes '__Z5int00v' and your C function becomes '__Z6int_00v', the last one I'm not sure about.

Learn how your compiler transforms your code. It's a very useful thing to know when finding bugs.
P.S. If anyone had any good examples or TUTs for making makefiles compatible with djgpp please let me know. Thanks again.
[timbot] Use cygwin, not djgpp [/timbot] - cygwin uses default makefiles & include dirs.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:LD Linking Problems... (2 of them...)

Post by Pype.Clicker »

you may like -fno-leading-underscore (info gcc for the exact syntax) which will make GCC use the 'real' name of a function/symbol instead of using _name.

The linker may indeed be sensitive to the order in which you pass .o files. May i suggest that you drop .o files in some directory distinct from the directory that has START.O and use something like

Code: Select all

    ld start.o bin/*.o
You may also love makefiles and linker scripts. info make and info ld will provide valuable tutorial about them ;)
astrocrep

Re:LD Linking Problems... (2 of them...)

Post by astrocrep »

I adjusted my batch file like pype.clicker said... thanks for the idea... and I am using the extern C to call my asm functions from C. But I am still unable to have my asm functions reach my c functions... I dunno what to do about this. Keep the ideas coming!

Thanks for the help guys,

Rich P.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:LD Linking Problems... (2 of them...)

Post by Candy »

From reply #4:
But I am still unable to have my asm functions reach my c functions... I dunno what to do about this.
From reply #2:
change your assembly code to conform to the naming of the c++-compiled code (your assembly function becomes '__Z5int00v' and your C function becomes '__Z6int_00v', the last one I'm not sure about.
Or reformulated, you use c++ name mangling. You do not understand it. Stop using it badly or start using it properly, IE: stop using the compiler as a C++ compiler, or call your C functions from assembly as I said above (__Z6int_00v) (again, name not sure).
astrocrep

Re:LD Linking Problems... (2 of them...)

Post by astrocrep »

Ive gotten past that problem...
Heres the flow of the code...

C++ Code loads up LDT with handlers... the wrappers are in asm and the asm calls C++ code...

The compiling and linking of the Installation of the handlers (ie the C++ code refrencing the ASM Code) is perfect no errors...

However the ASM Code the calls the C++ code fails upon linking... even if I remove my class refrences from it and compile it as a .c it still fails

asm code

Code: Select all

[extern _int_00]
[global _int00]
_int00:
     pusha
     push ds
     push es
     push fs
     push gs
     mov eax,0x10    ; Data segment
     mov ds,eax
     mov es,eax
     cld
     call _int_00    ; Divide by Zero #DE
     pop gs
     pop fs
     pop es
     pop ds
     popa
     iret
the linker cant find _int_00 actually its "void int_00(void)"

To clear up the confusion, int00 is the wrapper in asm, and int_00 is the c based handler...

Any other ideas ?

Thanks for the help,

Rich P.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:LD Linking Problems... (2 of them...)

Post by Candy »

You might want to search through the object file for all symbol names and find out what exactly its name becomes.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:LD Linking Problems... (2 of them...)

Post by Pype.Clicker »

Candy wrote: You might want to search through the object file for all symbol names and find out what exactly its name becomes.
which you can do with "objdump -x YourFile.O | less"

yes, "less" exists for Djgpp (and probably for cygwin aswell :) that's a wonderful tool for it can search regexps in the displayed document.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:LD Linking Problems... (2 of them...)

Post by Solar »

Candy wrote: what are "compile my os", "winxp" and "batch file" doing in the same post? Make has even been ported to windows-ish stuff, along with a decent shell, so you might want to consider that.
I can understand him here... make is a very complex beast, with both syntax and documentation being less than enlightening. (I'm struggling to get a generic Makefile up and running myself ATM.)
Pype.Clicker wrote: ...which you can do with "objdump -x YourFile.O | less"
I have no idea if "grep" is available with DJGPP (and I second Candy and timbot, get Cygwin from www.cygwin.com!), but if you have grep you can do:

objdump -d YourFile.O | grep "^[^ ]"

That yields much better-to-read output. ;-)
Every good solution is obvious once you've found it.
astrocrep

Re:LD Linking Problems... (2 of them...)

Post by astrocrep »

Ok I got cygwin... installed it w/ gcc and co. but using

Code: Select all

objdump -x or -d interrupts.o 
yeilds
File format not recognized...

Interrupts.o is from interrupts.asm compiled with nasm into an aout file format... dunno if that makes a difference

However under djgpp objdump does work and this is what I get:
(Sorry its long... but I dunno exactly what I am looking for)
(Also remember int00 is the wrapper in asm, and int_00 is the c based handler...)

Code: Select all


interrupts.o:     file format a.out-i386
interrupts.o
architecture: i386, flags 0x0000003f:
HAS_RELOC, EXEC_P, HAS_LINENO, HAS_DEBUG, HAS_SYMS, HAS_LOCALS
start address 0x00000000

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000258  00000000  00000000  00000020  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, CODE
  1 .data         00000000  00000258  00000258  00000278  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000258  00000258  00000000  2**3
                  ALLOC
SYMBOL TABLE:
00000000         *UND* 0000 00 01 _int_00
00000000 g       .text 0000 00 05 _int00
00000000         *UND* 0000 00 01 _int_01
0000001e g       .text 0000 00 05 _int01
00000000         *UND* 0000 00 01 _int_02
0000003c g       .text 0000 00 05 _int02
00000000         *UND* 0000 00 01 _int_03
0000005a g       .text 0000 00 05 _int03
00000000         *UND* 0000 00 01 _int_04
00000078 g       .text 0000 00 05 _int04
00000000         *UND* 0000 00 01 _int_05
00000096 g       .text 0000 00 05 _int05
00000000         *UND* 0000 00 01 _int_06
000000b4 g       .text 0000 00 05 _int06
00000000         *UND* 0000 00 01 _int_07
000000d2 g       .text 0000 00 05 _int07
00000000         *UND* 0000 00 01 _int_08
000000f0 g       .text 0000 00 05 _int08
00000000         *UND* 0000 00 01 _int_09
0000010e g       .text 0000 00 05 _int09
00000000         *UND* 0000 00 01 _int_10
0000012c g       .text 0000 00 05 _int10
00000000         *UND* 0000 00 01 _int_11
0000014a g       .text 0000 00 05 _int11
00000000         *UND* 0000 00 01 _int_12
00000168 g       .text 0000 00 05 _int12
00000000         *UND* 0000 00 01 _int_13
00000186 g       .text 0000 00 05 _int13
00000000         *UND* 0000 00 01 _int_14
000001a4 g       .text 0000 00 05 _int14
00000000         *UND* 0000 00 01 _int_16
000001c2 g       .text 0000 00 05 _int16
00000000         *UND* 0000 00 01 _int_17
000001e0 g       .text 0000 00 05 _int17
00000000         *UND* 0000 00 01 _int_18
000001fe g       .text 0000 00 05 _int18
00000000         *UND* 0000 00 01 _int_19
0000021c g       .text 0000 00 05 _int19
00000000         *UND* 0000 00 01 _testint
0000023a g       .text 0000 00 05 _int32


RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE 
00000012 DISP32            _int_00
00000030 DISP32            _int_01
0000004e DISP32            _int_02
0000006c DISP32            _int_03
0000008a DISP32            _int_04
000000a8 DISP32            _int_05
000000c6 DISP32            _int_06
000000e4 DISP32            _int_07
00000102 DISP32            _int_08
00000120 DISP32            _int_09
0000013e DISP32            _int_10
0000015c DISP32            _int_11
0000017a DISP32            _int_12
00000198 DISP32            _int_13
000001b6 DISP32            _int_14
000001d4 DISP32            _int_16
000001f2 DISP32            _int_17
00000210 DISP32            _int_18
0000022e DISP32            _int_19
0000024c DISP32            _testint
Well actually, studing it for a while I did notice this

Code: Select all

00000000         *UND* 0000 00 01 _int_00
00000000 g       .text 0000 00 05 _int00
UND means Undefined maybe ??
So means maybe Undefined int_00 (which is located in a cpp file)
the is being called in proc int00 (which is in the asm file)

But then it has a relocation table and I am not sure on how to handle that...

Thanks for the help all (sorry for being such a pain in the @$$)

Rich P.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:LD Linking Problems... (2 of them...)

Post by Pype.Clicker »

hmm ... i'm not sure it's a good idea to mix a.out (the nasm-generated .o file) with another format (i guesss .coff, for c++ generated files).

what does objdump give on gxx-generated files ?
astrocrep

Re:LD Linking Problems... (2 of them...)

Post by astrocrep »

Very Very Wierd...

this is from version.cpp

Code: Select all

version.o:     file format coff-go32
version.o
architecture: i386, flags 0x00000031:
HAS_RELOC, HAS_SYMS, HAS_LOCALS
start address 0x00000000

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000005c  00000000  00000000  000000b4  2**4
                  CONTENTS, ALLOC, LOAD, RELOC, CODE
  1 .data         0000003c  00000000  00000000  00000110  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  00000000  2**2
                  ALLOC
  3 .comment      00000014  00000000  00000000  0000014c  2**2
                  CONTENTS, DEBUGGING
SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x00000000 version.cpp
File 
[  2](sec  1)(fl 0x00)(ty   0)(scl   6) (nx 0) 0x00000032 LC0
[  3](sec  1)(fl 0x00)(ty   0)(scl   6) (nx 0) 0x00000048 LC1
[  4](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 0) 0x00000000 .text
[  5](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 __osfullName
[  6](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000001a __osfullVer
[  7](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000021 __osfullBuild
[  8](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000034 __osfullBNum
[  9](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000038 __osfullInternal
[ 10](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 __Z6osNamev
[ 11](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000a __Z9osVersionv
[ 12](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000014 __Z7osBuildv
[ 13](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000001e __Z10osBuildNumv
[ 14](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000028 __Z10osInternalv
[ 15](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000003e __Z10osCompDatev
[ 16](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000052 __Z10osCompTimev


RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE 
00000004 dir32             __osfullName
0000000e dir32             __osfullVer+0xffffffe6
00000018 dir32             __osfullBuild+0xffffffdf
00000022 dir32             __osfullBNum+0xffffffcc
0000002c dir32             __osfullInternal+0xffffffc8
00000042 dir32             .text
00000056 dir32             .text
in my linker script is am using

Code: Select all

OUTPUT_FORMAT("elf32-i386")
I have 2 other asm files that I use w/ my kernel... one for startup... Which actualy calls a c++ procedure, and one for functions like write_cr0 read_cr0 write_cr3 write_cr3, those two both work file... if I switch the -f aout in my nasm commandline I get more errors on all c -> asm or asm -> c calls...

Thanks

Rich P.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:LD Linking Problems... (2 of them...)

Post by Pype.Clicker »

and what does it work better when using nasm -f elf ?
astrocrep

Re:LD Linking Problems... (2 of them...)

Post by astrocrep »

using -f elf gives the same amount of errors as with aout... but it it better than coff

Code: Select all

kernel\interrupts.o: In function `_int00':
kernel\interrupts.o(.text+0x12): undefined reference to `_int_00'
kernel\interrupts.o: In function `_int01':
kernel\interrupts.o(.text+0x30): undefined reference to `_int_01'
kernel\interrupts.o: In function `_int02':
kernel\interrupts.o(.text+0x4e): undefined reference to `_int_02'
kernel\interrupts.o: In function `_int03':
kernel\interrupts.o(.text+0x6c): undefined reference to `_int_03'
kernel\interrupts.o: In function `_int04':
kernel\interrupts.o(.text+0x8a): undefined reference to `_int_04'
kernel\interrupts.o: In function `_int05':
kernel\interrupts.o(.text+0xa8): undefined reference to `_int_05'
kernel\interrupts.o: In function `_int06':
kernel\interrupts.o(.text+0xc6): undefined reference to `_int_06'
kernel\interrupts.o: In function `_int07':
kernel\interrupts.o(.text+0xe4): undefined reference to `_int_07'
kernel\interrupts.o: In function `_int08':
kernel\interrupts.o(.text+0x102): undefined reference to `_int_08'
kernel\interrupts.o: In function `_int09':
kernel\interrupts.o(.text+0x120): undefined reference to `_int_09'
kernel\interrupts.o: In function `_int10':
kernel\interrupts.o(.text+0x13e): undefined reference to `_int_10'
kernel\interrupts.o: In function `_int11':
kernel\interrupts.o(.text+0x15c): undefined reference to `_int_11'
kernel\interrupts.o: In function `_int12':
kernel\interrupts.o(.text+0x17a): undefined reference to `_int_12'
kernel\interrupts.o: In function `_int13':
kernel\interrupts.o(.text+0x198): undefined reference to `_int_13'
kernel\interrupts.o: In function `_int14':
kernel\interrupts.o(.text+0x1b6): undefined reference to `_int_14'
kernel\interrupts.o: In function `_int16':
kernel\interrupts.o(.text+0x1d4): undefined reference to `_int_16'
kernel\interrupts.o: In function `_int17':
kernel\interrupts.o(.text+0x1f2): undefined reference to `_int_17'
kernel\interrupts.o: In function `_int18':
kernel\interrupts.o(.text+0x210): undefined reference to `_int_18'
kernel\interrupts.o: In function `_int19':
kernel\interrupts.o(.text+0x22e): undefined reference to `_int_19'
kernel\interrupts.o: In function `_int32':
kernel\interrupts.o(.text+0x24c): undefined reference to `_testint'
Thanks for the help,
Keep the ideas coming

Rich P.
Post Reply