Page 1 of 1

LD linker help

Posted: Tue Apr 15, 2003 8:12 am
by drizzt
I've installed the LD linker ver2.13.90.0.2 and I've a problem with the MULTIBOOT header of my kernel.
Here is the first file I link with every other kernel object files (start.s):

Code: Select all

[BITS 32]
%define ADDRADJUST   0xBFF00000

; // Kernel virtual start address //
%define K_VIR_START   0xC0000000

; // Kernel physiscal start address //
%define K_PHYS_START   0x100000

; // Addressing macros //
%define SEGMENT(linear)   ((linear & 0xFFFF0000) >> 4)
%define OFFSET(linear)   (linear & 0xFFFF)

; // Paging constants //
%define   P_PRESENT    0x01
%define P_WRITE      0x02
%define P_USER      0x04
%define PAGE_SIZE   0x1000

%define K_PDE      0x1000   ; // Page directory          //
%define K_PTE      0x2000   ; // Kernel page table #0 (4MB)      //
%define I_PTE      0x3000   ; // First 4MB Identity-map page table   //

%macro memset 3
; // void memset(void *dest_ptr, int val, dword count); //
   mov edi, %1
   mov eax, %2
   mov ecx, %3
   cld
   o32 a32 rep stosb
%endmacro

%macro memcpy 3
; // void memcpy(void *dest_ptr, void *org_ptr, dword count); //
   mov edi, %1
   mov esi, %2
   mov ecx, %3
   cld
   o32 a32 rep movsb
%endmacro

; // Global variables //
GLOBAL _start
[EXTERN k_main]
[EXTERN K_STACK_END]

_start:
   jmp   entry

   ; // Here is the Multiboot Header (...required by GRUB!) //
   MULTIBOOT_PAGE_ALIGN equ (1 << 0)
   MULTIBOOT_MEMORY_INFO equ (1 << 1)

   MULTIBOOT_HEADER_MAGIC equ (0x1BADB002)
   MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
   CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

   ALIGN 4
   dd MULTIBOOT_HEADER_MAGIC
   dd MULTIBOOT_HEADER_FLAGS
   dd CHECKSUM

entry:
   ; // Turn off floppy motor //
   mov   dx, 0x03F2
   mov   al, 0x0C
   out   dx, al

   ; // Setup paging //
   memset K_PDE, 0, PAGE_SIZE

   ; // Setup first 4MB as identity-map (I_PTE) //
   mov   eax, (P_PRESENT | P_WRITE)
   mov   ecx, 1024
   mov   edi, I_PTE
   cld
Map_I_PTE:
   stosd
   add   eax, PAGE_SIZE
   loop   Map_I_PTE

   ; // Setup the kernel page table (K_PTE) //
   mov   eax, (K_PHYS_START | P_PRESENT | P_WRITE)
   mov   ecx, 1024
   mov   edi, K_PTE
Map_K_PTE:
   stosd
   add   eax, PAGE_SIZE
   loop   Map_K_PTE

   ; // Store the identity-map table (first 4MB) //
   mov dword [K_PDE], I_PTE | P_PRESENT | P_WRITE | P_USER

   ; // Store the kernel table (4MB of kernel virtual space) //
   mov dword [K_PDE+(K_VIR_START/(PAGE_SIZE*1024))*4], K_PTE | P_PRESENT | P_WRITE | P_USER

   ; // Map page directory into itself //
   mov dword [K_PDE+1023*4], K_PDE | P_PRESENT | P_WRITE | P_USER

   ; // Setup PDBR //
   mov   eax, K_PDE
   mov   cr3, eax

   ; // Enable paging //
   mov   eax, cr0
   or   eax, 0x80010000 ; CR0.PG = CR0.WP = 1
   mov   cr0, eax

   o32 a32 lgdt [gdtr]

   jmp   FLAT_CODE_SEL:paging_enabled

paging_enabled:
   ; // Update segment registers //
   mov   eax, FLAT_DATA_SEL
   mov   ds, eax
   mov   es, eax
   mov   ss, eax
   nop
   mov   fs, eax
   mov   gs, eax

   ; // Print a yellow smile on the screen //
   mov word [0xB8000], 0x0E02

   ; // Initialize kernel stack pointer //
   mov   esp, K_STACK_END

   ; // Jump to the kernel main //
   jmp   k_main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                   Global Descriptor Table                   ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdtr:
   dw (gdt_end - gdt - 1)   ; GDT limit
   dd gdt-ADDRADJUST   ; GDT linear address
gdt:
; Dummy descriptor      ; 0x00
   dw 0         ; Limit 15:0
   dw 0         ; Base 15:0
   db 0         ; Base 23:16
   db 0         ; Access byte (descriptor type)
   db 0         ; Limits 19:16, Flags
   db 0         ; Base 31:24

; Data descriptor
FLAT_DATA_SEL   equ     $-gdt   ; 0x08
   dw 0xFFFF      ; Limit 15:0
   dw 0         ; Base 15:0
   db 0         ; Base 23:16
   db 0x92            ; Data, Present, Writeable (1,0,0,1,0010)
   db 0xCF         ; G=1, D=1, 0, AVL=0, 1111=F: Limit/Length (1,1,0,0,1111)
   db 0         ; Base 31:24

; Code descriptor
FLAT_CODE_SEL   equ   $-gdt   ; 0x10
   dw 0xFFFF      ; Limit 15:0
   dw 0         ; Base 15:0
   db 0         ; Base 23:16
   db 0x9A         ; Code, Present, Non-conforming, Exec/read (1,0,0,1,1110)
   db 0xCF         ; G=1, D=1, 0, AVL=0, 1111=F: Limit/Length (1,1,0,0,1111)
   db 0         ; Base 31:24
gdt_end:

Re:LD linker help

Posted: Tue Apr 15, 2003 8:13 am
by drizzt
I link my kernel to an output file format "ELF32-i386"; here is my kernel.ld script:

Code: Select all

OUTPUT_FORMAT("elf32-i386")

K_VIR_START = 0xC0000000;
K_PHYS_START = 0x100000;
K_STACK_SIZE = 0x1000;
PAGE_SIZE = 0x1000;

ENTRY (_start)

SECTIONS
{
   .text K_VIR_START : AT(K_PHYS_START)
   {
      KERNEL_TEXT = .;
      *(.text)
      *(.rodata)
      . = ALIGN(PAGE_SIZE);
      KERNEL_END_TEXT = .;
   }

   .data : AT(K_PHYS_START + (KERNEL_DATA - KERNEL_TEXT))
   {
      KERNEL_DATA = .;
      *(.data)
      . = ALIGN(PAGE_SIZE);
      KERNEL_END_DATA = .;
   }

   .bss : AT(K_PHYS_START + (KERNEL_BSS - KERNEL_TEXT))
   {
      _stack = .;
      . += K_STACK_SIZE;
      _stack_end = .;
      K_STACK_END = .;

      KERNEL_BSS = .;
      *(.bss)
      *(COMMON)
      . = ALIGN(PAGE_SIZE);
      KERNEL_END_BSS = .;
   }
   . = ALIGN(PAGE_SIZE);
   KERNEL_TOP = .;
}
Then I use the command line:

Code: Select all

ld -g -T kernel.ld -nostdlib -o kernel.elf $(OBJS)
where $(OBJS) is the list
of every object file... (start.o is the first of the list)

If I check the multiboot header with the command "mbchk" the result is: "kernel.elf: No Multiboot header."
It seems to me strange, because with the old version (LD ver2.11.92.0.10) all goes well...

Could someone help me?! Thanks in advance...

Re:LD linker help

Posted: Tue Apr 15, 2003 10:18 pm
by Chris Giese
What does "readelf -l kernel.elf" say?

How about "objdump --private-headers --section-headers kernel.elf" ?

Re:LD linker help

Posted: Wed Apr 16, 2003 2:20 pm
by drizzt
What does "readelf -l kernel.elf" say?
Elf file type is EXEC (Executable file)
Entry point 0xc0000000
There are 4 program headers, starting at offset 52

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00000000 0x00000000 0x01305 0x01305 R 0x1000
LOAD 0x002000 0xc0000000 0x00100000 0x05000 0x05000 R E 0x1000
LOAD 0x007000 0xc0005000 0x00105000 0x01000 0x01000 RW 0x1000
LOAD 0x008000 0xc0006000 0x00107000 0x00000 0x15000 RW 0x1000

Section to Segment mapping:
Segment Sections...
00 .rodata.str1.1 .rodata.str1.32
01 .text
02 .data
03 .bss
How about "objdump --private-headers --section-headers kernel.elf" ?
kernel.elf: file format elf32-i386

Program Header:
LOAD off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**12
filesz 0x00001305 memsz 0x00001305 flags r--
LOAD off 0x00002000 vaddr 0xc0000000 paddr 0x00100000 align 2**12
filesz 0x00005000 memsz 0x00005000 flags r-x
LOAD off 0x00007000 vaddr 0xc0005000 paddr 0x00105000 align 2**12
filesz 0x00001000 memsz 0x00001000 flags rw-
LOAD off 0x00008000 vaddr 0xc0006000 paddr 0x00107000 align 2**12
filesz 0x00000000 memsz 0x00015000 flags rw-

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00005000 c0000000 00100000 00002000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00001000 c0005000 00105000 00007000 2**5
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00015000 c0006000 00107000 00008000 2**5
ALLOC
3 .comment 000004ab 00000000 00000000 00008000 2**0
CONTENTS, READONLY
4 .rodata.str1.1 00000459 000004ab 000004ab 000004ab 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .rodata.str1.32 000009e5 00000920 00000920 00000920 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA

Re:LD linker help

Posted: Wed Apr 16, 2003 10:05 pm
by Chris Giese
ELF GCC 2.x creates a single .rodata section for constant (read-only) data, but GCC 3.x creates multiple .rodata sections, including .rodata.str1.1 and .rodata.str1.32

Find this line in your linker script:
*(.rodata)

change it to
*(.rodata*)

then see if it links properly.

Re:LD linker help

Posted: Fri Apr 18, 2003 11:24 am
by drizzt
Now it works! Many thanks Chris!!!