Offset errors occurred when changing segment base address

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
babel92
Posts: 8
Joined: Thu Oct 25, 2012 9:21 am

Offset errors occurred when changing segment base address

Post by babel92 »

Hi there,

I ran into some really silly problems and cannot find any solution.
First of all, I setup a flat memory model. All the kernel segments have a base address of 0 (But in fact kernel code begin from 0x100000) and everything went well.
But today when I set the code segment descriptor to a base of 0x100000, things began to go mad. Seems that the IDT initializing C function had a wrong offset of my ISRs (For instance, INT 3 handling routine should be 0x68 instead of 0x100068 I used before. By the way, ISRs are written in asm) . I really don't know how to deal with it.

Thanks.

Compiling environment: Linux
ASM compiler: NASM
C compiler: cc
Linker: ld with script

Flags:

Code: Select all

NASMFLAGS=-f elf
CCFLAGS= -ffreestanding -c -m32 -nostdlib
LDFLAGS=-Ttext 0x100000 -shared --oformat binary -Bsymbolic -z defs -m elf_i386 -T ./link.ld
Linking scripts:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(boot_start)
phys = 0x00100000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(4096);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(4096);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(4096);
  }
  end = .;
}
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Offset errors occurred when changing segment base addres

Post by Brendan »

Hi,
babel92 wrote:I ran into some really silly problems and cannot find any solution.
First of all, I setup a flat memory model. All the kernel segments have a base address of 0 (But in fact kernel code begin from 0x100000) and everything went well.
But today when I set the code segment descriptor to a base of 0x100000, things began to go mad. Seems that the IDT initializing C function had a wrong offset of my ISRs (For instance, INT 3 handling routine should be 0x68 instead of 0x100068 I used before. By the way, ISRs are written in asm) . I really don't know how to deal with it.
For most things you're using offsets within the segment (and not actual addresses). If you load your code at 0x00100000 and were using "segment base = 0" and linking to 0x00100000 before; then if you change to "segment base = 0x00100000" you'd have to link it to 0.

For the address of the GDT and the address of the IDT (stored in the little structure that you load with "LGDT" and "LIDT"); the address is a linear address (and not a virtual address) and isn't effected by segmentation. This means that the linker will get them wrong and you need to adjust the virtual address the linker used into a linear address by adding the segment base to them. Of course if the segment base is zero the linker gets it right (because "linear = virtual + 0 = virtual" in that case).

However; segmentation is bad (useless, annoying, slow and deprecated) and it's likely that the best solution is to revert back to "all the kernel segments have a base address of 0". 8)


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
babel92
Posts: 8
Joined: Thu Oct 25, 2012 9:21 am

Re: Offset errors occurred when changing segment base addres

Post by babel92 »

Brendan wrote:Hi,
babel92 wrote:I ran into some really silly problems and cannot find any solution.
First of all, I setup a flat memory model. All the kernel segments have a base address of 0 (But in fact kernel code begin from 0x100000) and everything went well.
But today when I set the code segment descriptor to a base of 0x100000, things began to go mad. Seems that the IDT initializing C function had a wrong offset of my ISRs (For instance, INT 3 handling routine should be 0x68 instead of 0x100068 I used before. By the way, ISRs are written in asm) . I really don't know how to deal with it.
For most things you're using offsets within the segment (and not actual addresses). If you load your code at 0x00100000 and were using "segment base = 0" and linking to 0x00100000 before; then if you change to "segment base = 0x00100000" you'd have to link it to 0.

For the address of the GDT and the address of the IDT (stored in the little structure that you load with "LGDT" and "LIDT"); the address is a linear address (and not a virtual address) and isn't effected by segmentation. This means that the linker will get them wrong and you need to adjust the virtual address the linker used into a linear address by adding the segment base to them. Of course if the segment base is zero the linker gets it right (because "linear = virtual + 0 = virtual" in that case).

However; segmentation is bad (useless, annoying, slow and deprecated) and it's likely that the best solution is to revert back to "all the kernel segments have a base address of 0". 8)


Cheers,

Brendan
Finally I decide to undo all the changes to my code (A lot of work, unfortunately :evil: ) according to your suggestion, and going to learn about some paging stuff to make it better.
Thanks! :)
Post Reply