LD linker help

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.
Post Reply
drizzt

LD linker help

Post 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:
drizzt

Re:LD linker help

Post 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...
Chris Giese

Re:LD linker help

Post by Chris Giese »

What does "readelf -l kernel.elf" say?

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

Re:LD linker help

Post 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
Chris Giese

Re:LD linker help

Post 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.
drizzt

Re:LD linker help

Post by drizzt »

Now it works! Many thanks Chris!!!
Post Reply