Page 3 of 4

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 9:49 pm
by austanss
This is my GDT in it's entirety:

Code: Select all

global loadGDT64
global GDT64

loadGDT64:
	lgdt [GDT64.Pointer]        ; Load the new GDT pointer
	ret


GDT64:                           ; Global Descriptor Table (64-bit).
    .Null: equ $ - GDT64         ; The null descriptor.
    dw 0xFFFF                    ; Limit (low).
    dw 0                         ; Base (low).
    db 0                         ; Base (middle)
    db 0                         ; Access.
    db 1                         ; Granularity.
    db 0                         ; Base (high).
    .Code: equ $ - GDT64         ; The code descriptor.
    dw 0                         ; Limit (low).
    dw 0                         ; Base (low).
    db 0                         ; Base (middle)
    db 10011010b                 ; Access (exec/read).
    db 10101111b                 ; Granularity, 64 bits flag, limit19:16.
    db 0                         ; Base (high).
    .Data: equ $ - GDT64         ; The data descriptor.
    dw 0                         ; Limit (low).
    dw 0                         ; Base (low).
    db 0                         ; Base (middle)
    db 10010010b                 ; Access (read/write).
    db 00000000b                 ; Granularity.
    db 0                         ; Base (high).
    .Pointer:                    ; The GDT-pointer.
    dw $ - GDT64 - 1             ; Limit.
    dq GDT64                     ; Base.

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 9:53 pm
by Octocontrabass
rizxt wrote:Usually when I read the RIP value, it points to null bytes.
How exactly are you reading the data at RIP?
rizxt wrote:This is my GDT in it's entirety:
Those are segment descriptors, I'm asking about segment selectors.

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 9:54 pm
by austanss
Octocontrabass wrote:
rizxt wrote:Usually when I read the RIP value, it points to null bytes.
How exactly are you reading the data at RIP?
rizxt wrote:This is my GDT in it's entirety:
Those are segment descriptors, I'm asking about segment selectors.
I'm using QEMU to dump guest memory, then I ndisasm the memory dump and look for the address.

Not sure what you mean then, because you pointed to a line of my code that loaded the GDT...

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:01 pm
by Octocontrabass
rizxt wrote:I'm using QEMU to dump guest memory,
How are you doing that? (Did you know QEMU has a built-in disassembler?)
rizxt wrote:Not sure what you mean then, because you pointed to a line of my code that loaded the GDT...
You do know what a segment selector is, right? (If not, maybe check the Intel or AMD manuals, or see if any pages on the wiki explain it.)

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:26 pm
by austanss
AMD APM Volume 2, section 4.5.1 wrote: Segment selectors are pointers to specific entries in the global and local descriptor tables. Figure 4-3 shows the segment selector format.Figure 4-3. Segment SelectorThe selector format consists of the following fields:


Selector Index Field.
Bits 15:3.

The selector-index field specifies an entry in the descriptor table. Descriptor-table entries are eight bytes long, so the selector index is scaled by 8 to form a byte offset into the descriptor table. The offset is then added to either the global or local descriptor-table base address (as indicated by the table-index bit) to form the descriptor-entry address in virtual-address space.

Some descriptor entries in long mode are 16 bytes long rather than 8 bytes (see “Legacy Segment Descriptors” on page 84 for more information on long-mode descriptor-table entries). These expanded descriptors consume two entries in the descriptor table. Long mode, however, continues to scale the selector index by eight to form the descriptor-table offset. It is the responsibility of system software to assign selectors such that they correctly point to the start of an expanded.


Table Indicator (TI) Bit.
Bit 2.

The TI bit indicates which table holds the descriptor referenced by the selector index. When TI=0 the GDT is used and when TI=1 the LDT is used. The descriptor-table base address is read from the appropriate descriptor-table register and added to the scaled selector index as described above.

Requestor Privilege-Level (RPL) Field.
Bits 1:0.

The RPL represents the privilege level (CPL) the processor is operating under at the time the selector is created.

RPL is used in segment privilege-checks to prevent software running at lesser privilege levels from accessing privileged data. See “Data-Access Privilege Checks” on page 101 and “Control-Transfer Privilege Checks” on page 104 for more information on segment privilege-checks.


Null Selector.

Null selectors have a selector index of 0 and TI=0, corresponding to the first entry in the GDT. However, null selectors do not reference the first GDT entry but are instead used to invalidate unused segment registers. A general-protection exception (#GP) occurs if a reference is made to use a segment register containing a null selector in non-64-bit mode. By initializing unused segment registers with null selectors software can trap references to unused segments.Null selectors can only be loaded into the DS, ES, FS and GS data-segment registers, and into the LDTR descriptor-table register. A #GP occurs if software attempts to load the CS register with a null selector or if software attempts to load the SS register with a null selector in non 64-bit mode or at CPL 3.

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:34 pm
by austanss
OH! The segment selectors are ds, gs, fs, etc., right???

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:38 pm
by Octocontrabass
Well, the values stored in the segment registers, but yes. Those need to be updated to point to the correct descriptors in your GDT, otherwise the value you save and restore during an interrupt won't be valid, and you'll get an exception after handling the interrupt.

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:38 pm
by austanss
Aight so, what you are saying is that when I saved the data selector, and pushed it to the stack, I might have popped the incorrect value of the stack?

EDIT: No, you are saying the values were invalid to begin with. After reading the AMD manuals, I might have a fix for it...

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:41 pm
by Octocontrabass
Mmmaybe? You popped the value you pushed. The problem is that the value you pushed was not a valid selector for your GDT.

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:45 pm
by austanss
So, I assume I am supposed to load the GDT64.Code descriptor into the cs register, and GDT64.Data descriptor into the ds register? If so, I don't know how. Loading the contents throws a triple fault and loading the pointer doesn't even assemble.

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:46 pm
by austanss
OH no. I am supposed to define a 16-bit selector that points to the descriptor, and then load those into the registers.

Am I right?

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:51 pm
by Octocontrabass
That's right.

Loading CS can be tricky since you can't use MOV; you have to use a control flow instruction like JMP, CALL, or RET.

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 10:52 pm
by austanss
The ****? Can you give me an example code or something on how to load CS?

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 11:03 pm
by Octocontrabass
Something like this: (untested)

Code: Select all

section .text

	jmp far [pointer]
address:
	; next instruction
	
section .rodata

pointer:
	dq address
	dw CODE_SELECTOR_HERE

Re: converting 32-bit IDT to 64-bit IDT

Posted: Tue Dec 01, 2020 11:05 pm
by austanss
Aight, one last question:

In the AMD manuals it says the offset is 8 bits long. This is obviously not enough to fit a memory address, what am I supposed to put in there to make it point to my descriptors?