Error: Entry point isn't in a segment

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
User avatar
KemyLand
Member
Member
Posts: 213
Joined: Mon Jun 16, 2014 5:33 pm
Location: Costa Rica

Error: Entry point isn't in a segment

Post by KemyLand »

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: Select all

.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: Select all

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
Happy New Code!
Hello World in Brainfuck :D:

Code: Select all

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
[/size]
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Error: Entry point isn't in a segment

Post by sortie »

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.
User avatar
eryjus
Member
Member
Posts: 286
Joined: Fri Oct 21, 2011 9:47 pm
Libera.chat IRC: eryjus
Location: Tustin, CA USA

Re: Error: Entry point isn't in a segment

Post by eryjus »

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

The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal

"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
naegelejd
Posts: 12
Joined: Thu Oct 09, 2014 5:09 pm

Re: Error: Entry point isn't in a segment

Post by naegelejd »

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.
User avatar
KemyLand
Member
Member
Posts: 213
Joined: Mon Jun 16, 2014 5:33 pm
Location: Costa Rica

Re: Error: Entry point isn't in a segment

Post by KemyLand »

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.
Happy New Code!
Hello World in Brainfuck :D:

Code: Select all

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
[/size]
Post Reply