OSDev.org
https://forum.osdev.org/

Error: Entry point isn't in a segment
https://forum.osdev.org/viewtopic.php?f=1&t=28796
Page 1 of 1

Author:  KemyLand [ Sun Nov 30, 2014 2:25 pm ]
Post subject:  Error: Entry point isn't in a segment

Hi!

I was trying to follow the wiki's Higher-Half tutorial. It looked too easy... Simple arithmetic and that's it. But when I compile and run all the stuff, GRUB 2.00 revenges again :x . A little message appears, saying:
GRUB 2.00 wrote:
error: entry point isn't in a segment.
error: you need to load the kernel first.

Press any key to continue...


What am I doing wrong? I saw that in the tutorial, the .text section wasn't page-aligned. I did it, and the same error apperars. Then I saw the tutorial puts the Multiboot header in the .text section, but that's just awful and dangerous. I changed my code, just for test, and obviously a "multiboot not found" error appeared; undoed that. Here's the relevant code (in file /arch/x86/init/bootstrap.S):
Code:
.set ALIGN,    1<<0             # align loaded modules on page boundaries
.set MEMINFO,  1<<1             # provide memory map
.set FLAGS,    ALIGN | MEMINFO  # this is the Multiboot 'flag' field
.set MAGIC,    0x1BADB002       # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot

.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
.align 0x1000

.section .stack, "aw", @nobits
stackBottom:
   .skip 16384
stackTop:

.set KVIRT_BASE, 0xC0000000
.set KPAGE_NUM,   (KVIRT_BASE >> 22)

.section .data
pageDirectory:
   .long 0x00000083
   .fill (KPAGE_NUM - 1), 4, 0x00000000
   .long 0x00000083
   .fill (1024 - KPAGE_NUM - 1), 4, 0x00000000

.section .text
.global __start__
.set __start__, (setup - 0xC0000000)
setup:
   movl (pageDirectory - KVIRT_BASE), %eax
   movl %ecx, %cr3
   
   movl %cr4, %ecx
   orl $0x00000010, %ecx
   movl %ecx, %cr4
   
   movl %cr0, %ecx
   orl $0x80000000, %ecx
   movl %ecx, %cr0
   
   lea (realstart), %ecx
   jmp *%ecx
   
realstart:
   movl $0x00000000, (pageDirectory)
   invlpg (0)
   
   movl $stackTop, %esp
   movl %esp, %ebp
   
   push %ebx
   push %eax
   call KernelInit
   
   cli
   hlt
.hang:
   jmp .hang


And here's the relevant linker script:
Code:
ENTRY(__start__)
OUTPUT_FORMAT(elf32-i386)

SECTIONS {
   . = 0xC0100000;

   .text : ALIGN(0x1000) : AT(ADDR(.text) - 0xC0000000) {
       *(.multiboot)
       *(.text)
   }
   
   .rodata ALIGN(0x1000) : AT(ADDR(.rodata) - 0xC0000000) {
       *(.rodata*)
   }
   
   .data ALIGN (0x1000) : AT(ADDR(.data) - 0xC0000000) {
       *(.data)
   }

   .bss : AT(ADDR(.bss) - 0xC0000000) {
       *(COMMON)
       *(.bss)
       *(.stack)
   }
   
   __KEND__ = .;
}


The wiki says I shouldn't calculate the physical address of __start__ myself, or I'll get the mentioned error. But I'm not doing it :-k

Author:  sortie [ Sun Nov 30, 2014 4:13 pm ]
Post subject:  Re: Error: Entry point isn't in a segment

May I suggest you don't mix multiboot and higher half? It's not pretty when code has to relocate itself. I recommend you use a bootloader (perhaps a custom one) that enables paging when loading your kernel and maps it already to virtual locations. You pass the locations of where the paging tables are mapped and the memory map to the kernel, it can then bootstrap itself and take control of paging. You then simply link the kernel at somewhere location you want it.

I blew some nukes on the wiki and got rid of some of the duplicated and ill-advised higher half tutorials, just leaving not-entirely-bad ones. We need a good rewrite, I'll get around to that eventually, but I believe it's bad design for code to relocate itself and that paging-enabling is a bootloader responsibility; therefore multiboot is a broken design in my opinion.

Another approach could be to have two kernels, with one as a normal multiboot kernel at 1 MiB, and another as the real kernel that as is passed as an initrd to the wrapper kernel, the wrapper kernel enables paging and loads the real kernel according to its ELF headers and passes control to it. This has the advantage of not being a full custom bootloader.

Author:  eryjus [ Sun Nov 30, 2014 9:18 pm ]
Post subject:  Re: Error: Entry point isn't in a segment

I'm successfully using multiboot and 64 bit higher half. The biggest problems are the elf page size and the structure alignments.

I'm on my phone now, but you can check out my make file and loader from the link below.

EDIT: Now that I have the benefit of a larger screen, I see I had the same problem. The way I overcame this in my code was to skip the tricky stuff and simply set the entry point. In other words, set your entry point to be setup.

Finally, I would pull your multiboot and initial 32-bit setup code into its own elf section and put that first in the linker script. I put my entry point in a .boot section and told the linker to put it right behind my multiboot data structures. Then, I set my .text section in the higher virtual address.

Author:  naegelejd [ Mon Dec 01, 2014 11:12 am ]
Post subject:  Re: Error: Entry point isn't in a segment

Try consolidating your "__start__" and "setup" address. Don't subtract 0xC0000000 from setup.

I learned this the hard way a few week ago. Grub's multiboot will expect the start symbol to be located above 0xC0000000.

You can see my (very similar) linker.ld and start.s script for comparison.

Author:  KemyLand [ Mon Dec 01, 2014 3:08 pm ]
Post subject:  Re: Error: Entry point isn't in a segment

naegelejd wrote:
Try consolidating your "__start__" and "setup" address. Don't subtract 0xC0000000 from setup.

I learned this the hard way a few week ago. Grub's multiboot will expect the start symbol to be located above 0xC0000000.

You can see my (very similar) linker.ld and start.s script for comparison.


Thanks, that solved it! I'll edit the wiki with this information :wink: . Now I have another (minor) problem. How can I debug the __start__ function (there's no setup now) with GDB? It triple faults inmediately. Probably I did a bad conversion between NASM and GAS code #-o . I'll try several combinations until GDB breaks at realstart.

Edit: I've finally managed to debug with GDB, even in this situation (command break *something - 0xC0000000), then lots of stepi and info reg ecx. Thanks to all of your for your help! I'll take in account sortie's suggestion BTW.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/