Commit 36c7cc0f authored by PhoeniX's avatar PhoeniX

Full working SMP

Now SMP initialization is supported on QEMU, vmWare, VirtualBox, and on
some PCs that I tested.
parent 707884b1
CC=x86_64-w64-mingw32-gcc
LD=x86_64-w64-mingw32-ld
OBJCOPY=x86_64-w64-mingw32-objcopy
# PhoeniX OS Makefile
# Copyright (C) 2013 PhoeniX
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
PREFIX=
ifeq ($(OS),Windows_NT)
PREFIX=x86_64-w64-mingw32-
endif
CC=$(PREFIX)gcc
LD=$(PREFIX)ld
OBJCOPY=$(PREFIX)objcopy
CFLAGS=-c -nostdlib -s -m64 -O2
BIN=bin/pxkrnl
all: $(BIN) clean
$(BIN): obj/x32to64.o obj/boot.o obj/memory.o obj/pxlib.o obj/interrupts.o obj/multiboot_info.o obj/modules.o obj/modules-linked.o
$(BIN): obj/x32to64.o obj/boot.o obj/memory.o obj/pxlib.o obj/interrupts.o obj/multiboot_info.o obj/modules.o obj/smp_init.o obj/smp.o obj/modules-linked.o
$(LD) -T ld.script -belf64-x86-64 -o $(BIN) -s --nostdlib $?
$(OBJCOPY) $(BIN) -Felf32-i386
obj/boot.o : src/boot.cpp obj
......@@ -14,20 +35,27 @@ obj/pxlib.o : src/pxlib.cpp obj
$(CC) $(CFLAGS) src/pxlib.cpp -o $@
obj/memory.o : src/memory.cpp obj
$(CC) $(CFLAGS) src/memory.cpp -o $@
obj/smp.o : src/smp.cpp obj
$(CC) $(CFLAGS) src/smp.cpp -o $@
obj/interrupts.o : src/interrupts.cpp obj
$(CC) $(CFLAGS) src/interrupts.cpp -o $@
obj/multiboot_info.o : src/multiboot_info.cpp obj
$(CC) $(CFLAGS) src/multiboot_info.cpp -o $@
obj/modules.o : src/modules.cpp obj
$(CC) $(CFLAGS) src/modules.cpp -o $@
$(CC) $(CFLAGS) -Wno-multichar src/modules.cpp -o $@
obj/x32to64.o : src/x32to64.s obj
fasm src/x32to64.s obj/x32to64.o
obj/smp_init.o : src/smp.s obj
fasm src/smp.s obj/smp_init.b
$(OBJCOPY) -Oelf64-x86-64 -Bi386 -Ibinary --rename-section .data=.smp_init obj/smp_init.b obj/smp_init.o
obj/modules-linked.o : mod/hello.o
$(OBJCOPY) -Oelf64-x86-64 -Bi386 -Ibinary --rename-section .data=.modules $? $@
mod/hello.o : modules/hello/hello.cpp
$(CC) $(CFLAGS) $? -o $@
$(OBJCOPY) -Oelf64-x86-64 -Bi386 $@
$(OBJCOPY) -Oelf64-x86-64 $@
clean:
rm -rf obj mod
obj:
mkdir -p obj mod
launch:
qemu -kernel $(BIN) -smp 8
No preview for this file type
/* PhoeniX OS Linking script
** Copyright (C) 2013 PhoeniX
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
OUTPUT_FORMAT(pei-x86-64)
SECTIONS
{
. = SIZEOF_HEADERS;
. = ALIGN(__section_alignment__);
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :
. = 0x401000;
.text :
{
*(.init)
*(.init)
*(.text32)
*(.text)
*(SORT(.text$*))
*(.text.*)
_smp_init = . ;
*(.smp_init)
_smp_end = . ;
*(.gnu.linkonce.t.*)
. = ALIGN(8);
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
LONG (-1); LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0); LONG (0);
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
LONG (-1); LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0); LONG (0);
*(.fini)
PROVIDE (etext = .);
*(.gcc_except_table)
*(.fini)
}
.data BLOCK(__section_alignment__) :
. = ALIGN (0x1000);
.data :
{
__data_start__ = . ;
*(.data)
*(SORT(.data$*))
__data_end__ = . ;
}
.rdata BLOCK(__section_alignment__) :
. = ALIGN (0x1000);
.rdata :
{
__rdata_start__ = . ;
*(.rdata)
*(SORT(.rdata$*))
__rdata_end__ = . ;
}
.bss BLOCK(__section_alignment__) :
. = ALIGN (0x1000);
.bss :
{
__bss_start__ = . ;
*(.bss)
*(COMMON)
__bss_end__ = . ;
}
.modules BLOCK(__section_alignment__) :
. = ALIGN (0x1000);
.modules :
{
__modules_start__ = . ;
*(.modules)
......
// PhoeniX OS Startup file
// Copyright (C) 2013 PhoeniX
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "pxlib.h"
int main()
......@@ -5,5 +21,7 @@ int main()
clrscr();
memory_init();
interrupts_init();
smp_init();
modules_init();
process_loop();
}
// PhoeniX OS Interrupts subsystem
// Copyright (C) 2013 PhoeniX
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "interrupts.h"
PIDT idt = 0;
PHCODE handlers = 0;
char* handlers = 0;
INTERRUPT32 interrupts32[256];
asm volatile("\
_interrupt_handler:\n\
......@@ -25,8 +41,6 @@ push %r14\n\
push %r15\n\
\
call interrupt_handler\n\
movb $0x20, %al\n\
outb %al, $0x20\n\
\
popq %r15\n\
popq %r14\n\
......@@ -42,6 +56,8 @@ popq %rbp\n\
popq %rbx\n\
popq %rdx\n\
popq %rcx\n\
movb $0x20, %al\n\
outb %al, $0x20\n\
popq %rax\n\
\
add $2, %esp\n\
......@@ -57,30 +73,39 @@ void interrupt_handler(){
for(int i=0;i<7;i++)
{printq(rsp[i]); print("\n");}
for(;;);
} else if(al!=0x20) {
print("INT "); prints(al); print("\n");
}
}
void interrupts_init()
{
idt = (PIDT)malloc(sizeof(IDT));
idt = (PIDT)malloc(sizeof(IDT),0x1000);
idt->rec.limit = sizeof(idt->ints) -1;
idt->rec.addr = &idt->ints[0];
handlers = (PHCODE)malloc(sizeof(HCODE)*256);
handlers = (char*)malloc(9*256,0x1000);
void* addr;
asm("mov $_interrupt_handler,%q0":"=a"(addr));
for(int i=0; i<256; i++){
handlers[i].push_w = 0x6866;
handlers[i].intr = i & 0xFF;
handlers[i].push = 0x68;
handlers[i].addr = (_int64)addr;
handlers[i].ret = 0xC3;
_uint64 jmp_from = (_uint64)&handlers[9*i+ 4];
_uint64 jmp_to = (_uint64)addr;
_uint64 diff = jmp_to - jmp_from - 5;
handlers[9*i+ 0] = 0x66; // push
handlers[9*i+ 1] = 0x68; // short
handlers[9*i+ 2] = i & 0xFF; // int_num [2]
handlers[9*i+ 3] = 0x00;
handlers[9*i+ 4] = 0xE9; // jmp rel
handlers[9*i+ 5] = (diff ) & 0xFF;
handlers[9*i+ 6] = (diff >> 8) & 0xFF;
handlers[9*i+ 7] = (diff >> 16) & 0xFF;
handlers[9*i+ 8] = (diff >> 24) & 0xFF;
idt->ints[i].zero = 0;
idt->ints[i].reserved = 0;
idt->ints[i].selector = 8;
idt->ints[i].type = 0x8E; // P[7]=1, DPL[65]=0, S[4]=0, Type[3210] = E
idt->ints[i].offset_low = ((_int64)(&handlers[i]) >> 0) & 0xFFFF;
idt->ints[i].offset_middle = ((_int64)(&handlers[i]) >> 16) & 0xFFFF;
idt->ints[i].offset_high = ((_int64)(&handlers[i]) >> 32) & 0xFFFFFFFF;
idt->ints[i].offset_low = ((_int64)(&handlers[9*i]) >> 0) & 0xFFFF;
idt->ints[i].offset_middle = ((_int64)(&handlers[9*i]) >> 16) & 0xFFFF;
idt->ints[i].offset_high = ((_int64)(&handlers[9*i]) >> 32) & 0xFFFFFFFF;
}
outportb(0x20, 0x11);
......@@ -91,6 +116,7 @@ void interrupts_init()
outportb(0xA1, 0x02);
outportb(0x21, 0x01);
outportb(0xA1, 0x01);
outportb(0x21, 0);
outportb(0xA1, 0);
asm volatile( "lidtq %0\nsti"::"m"(idt->rec));
......
// PhoeniX OS Interrupts subsystem
// Copyright (C) 2013 PhoeniX
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef INTERRUPTS_H
#define INTERRUPTS_H
#include "pxlib.h"
typedef struct {
short push_w;
short intr;
char push;
long addr;
char ret;
} __attribute__ ((packed)) HCODE, *PHCODE;
#pragma pack(push,1)
typedef struct {
short offset_low;
short selector;
......@@ -27,7 +37,8 @@ typedef struct {
typedef struct {
short limit;
void* addr;
} __attribute__ ((packed)) IDTR, *PIDTR;
} IDTR, *PIDTR;
#pragma pack(pop)
typedef struct {
INTERRUPT64 ints[256];
IDTR rec;
......
// PhoeniX OS Memory subsystem
// Copyright (C) 2013 PhoeniX
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "pxlib.h"
PGRUB grub_data;
PPTE pagetable = (PPTE)0x10000;
PPTE pagetable = (PPTE)0x20000;
PALLOCTABLE allocs = 0;
void* first_free = (void*)0x10000;
void* first_free = (void*)0x2000;
_uint64 last_page = 1;
PPML4E get_page(void* base_addr)
{
......@@ -17,7 +33,7 @@ PPML4E get_page(void* base_addr)
}
void memory_init()
{
asm("movq $_start, %q0":"=a"(kernel_data.kernel)); kernel_data.stack = 0x1000; kernel_data.stack_top = 0x10000;
asm("movq $_start, %q0":"=a"(kernel_data.kernel)); kernel_data.stack = 0x1000; kernel_data.stack_top = 0x2000;
asm("movq $__data_start__, %q0":"=a"(kernel_data.data));
asm("movq $__rdata_end__, %q0":"=a"(kernel_data.data_top));
asm("movq $__bss_start__, %q0":"=a"(kernel_data.bss));
......@@ -73,7 +89,7 @@ void memory_init()
(*(_uint64*)(get_page((void*)0x00000000))) &= 0xFFFFFFFFFFFFFFF0; // BIOS Data
for(_uint64 addr = 0x0A0000; addr < 0x0C8000; addr += 0x1000) // Video data & VGA BIOS
(*(_uint64*)(get_page((void*)addr))) &= ~4;
for(_uint64 addr = 0x0C8000; addr < 0x0EF000; addr += 0x1000) // Reserved for many systems
for(_uint64 addr = 0x0C8000; addr < 0x0F0000; addr += 0x1000) // Reserved for many systems
(*(_uint64*)(get_page((void*)addr))) &= ~4;
for(_uint64 addr = 0x0F0000; addr < 0x100000; addr += 0x1000) // BIOS Code
(*(_uint64*)(get_page((void*)addr))) &= ~4;
......@@ -85,7 +101,6 @@ void memory_init()
(*(_uint64*)(get_page((void*)addr))) &= ~4;
for(_uint64 addr = kernel_data.bss; addr < (kernel_data.bss_top & 0xFFFFFFFFFFFFF000) + 0x1000; addr += 0x1000) // PXOS BSS
(*(_uint64*)(get_page((void*)addr))) &= ~4;
(*(_uint64*)(get_page((void*)pagetable))) &= ~4; // Setting pagetable pages as system
for(short i = 0; i < 512; i++) {
PPDE pde = pagetable[i];
......@@ -134,8 +149,11 @@ void memory_init()
} else {
kernel_data.cmdline = 0;
}
if((kernel_data.flags & 8) == 8){
if(((kernel_data.flags & 8) == 8)&&(kernel_data.mods != 0)){
PMODULE mod = kernel_data.mods = (PMODULE)malloc(sizeof(MODULE));
mod->start = 0;
mod->end = 0;
mod->next = 0;
int i=0;
while(modules[i].start != 0){
mod->start = (void*)((_uint64)modules[i].start & 0xFFFFFFFF);
......@@ -150,7 +168,7 @@ void memory_init()
void memmap()
{
char *m = (char*)0xB8000;
int i;
_uint64 i;
for(i = 0; i < 0x7D0000; i+=0x1000) {
void *p = get_page((void*)i);
char c = 0, cl;
......@@ -171,6 +189,25 @@ void memmap()
m++;
}
}
void* salloc(void* mem)
{
_uint64 i = (_uint64)(mem) >> 12;
void *addr = (void*)(i << 12);
PDE pde = (PDE)((_uint64)pagetable[(i >> 27) & 0x1FF] & 0xFFFFFFFFFFFFF000);
if(pde == 0){
pagetable[(i >> 27) & 0x1FF] = (PPDE)((_uint64)(pde = (PDE)((_uint64)palloc(1))) | 3);
}
PDPE pdpe = (PDPE)((_uint64)pde[(i >> 18) & 0x1FF] & 0xFFFFFFFFFFFFF000);
if(pdpe == 0){
pde[(i >> 18) & 0x1FF] = (PPML4E)((_uint64)(pdpe = (PDPE)((_uint64)palloc(1))) | 3);
}
PPML4E page = (PPML4E)((_uint64)pdpe[(i >> 9) & 0x1FF] & 0xFFFFFFFFFFFFF000);
if(page == 0){
pdpe[(i >> 9) & 0x1FF] = (void*)((_uint64)(page = (PPML4E)((_uint64)palloc(1))) | 3);
}
page[i & 0x1FF] = (void*)(((_uint64)addr) | 3);
return addr;
}
void* palloc(char sys)
{
void *addr; PPML4E page;
......@@ -309,4 +346,12 @@ void mfree(void* addr)
if(t->next == 0) return;
t = (PALLOCTABLE)t->next;
}
}
\ No newline at end of file
}
void memcpy(char *dest, char *src, _uint64 count) {
while(count){
*dest = *src;
dest++;
src++;
count--;
}
}
// PhoeniX OS Memory subsystem
// Copyright (C) 2013 PhoeniX
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef MEMORY_H
#define MEMORY_H
#include "pxlib.h"
......@@ -38,7 +54,9 @@ typedef struct {
extern PGRUB grub_data;
extern void memmap();
extern void memory_init();
extern void* salloc(void* mem);
extern void* palloc(char sys = 0);
extern void* malloc(_uint64 size, int align = 4);
extern void mfree(void* addr);
extern void memcpy(char *dest, char *src, _uint64 count);
#endif
// PhoeniX OS Modules subsystem
// Copyright (C) 2013 PhoeniX
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "modules.h"
typedef struct {
struct {
long EI_MAG;
char EI_CLASS;
char EI_DATA;
char EI_VERSION;
char EI_OSABI;
char EI_ABIVERSION;
char EI_PAD;
char reserved[6];
} e_ident;
unsigned short e_type; /* Object file type */
unsigned short e_machine; /* Machine type */
unsigned long e_version; /* Object file version */
void* e_entry; /* Entry point address */
_uint64 e_phoff; /* Program header offset */
_uint64 e_shoff; /* Section header offset */
unsigned long e_flags; /* Processor-specific flags */
unsigned short e_ehsize; /* ELF header size */
unsigned short e_phentsize; /* Size of program header entry */
unsigned short e_phnum; /* Number of program header entries */
unsigned short e_shentsize; /* Size of section header entry */
unsigned short e_shnum; /* Number of section header entries */
unsigned short e_shstrndx; /* Section name string table index */
} ELF64HDR, *PELF64HDR;
typedef struct
{
unsigned long sh_name;
unsigned long sh_type;
_uint64 sh_flags;
_uint64 sh_addr;
_uint64 sh_offset;
_uint64 sh_size;
unsigned long sh_link;
unsigned long sh_info;
_uint64 sh_addralign;
_uint64 sh_entsize;
} ELF64SECT, *PELF64SECT;
PMODULEINFO load_module_elf(void* addr)
{
// Parsing ELF
......@@ -55,22 +33,24 @@ PMODULEINFO load_module_elf(void* addr)
printq((_uint64)addr); print(" - "); print("ELF\n");
PELF64SECT sect = (PELF64SECT)((_uint64)addr + e_hdr->e_shoff);
print("#\tST\tSA\t\t\tSO\t\t\tSS\t\t\tSN\n");
for(int i = 0; i < e_hdr->e_shnum; i++){
printb(i);
print("\t");
printb(sect[i].sh_type);
print("\t");
printl(sect[i].sh_addr);
print("\t");
printl(sect[i].sh_offset);
print("\t");
printl(sect[i].sh_size);
print("\t");
print((char*)((_uint64)addr + sect[e_hdr->e_shstrndx].sh_offset + sect[i].sh_name));
print("\n");
PMODULEINFO mod = (PMODULEINFO)malloc(sizeof(MODULEINFO));
mod->section_count = 0;
for(int i = 0; i < e_hdr->e_shnum; i++)
if((sect[i].sh_type == 1)||(sect[i].sh_type == 8))
mod->section_count++;
mod->sections = (PSECTION)malloc(mod->section_count*sizeof(SECTION));
int i = 0, s = 0;
return mod;
while(i < mod->section_count){
if((sect[s].sh_type == 1)||(sect[s].sh_type == 8)){
mod->sections[i].offset = (void*)((_uint64)addr + sect[s].sh_offset);
mod->sections[i].size = sect[s].sh_size;
mod->sections[i].name = strcpy((char*)((_uint64)addr + sect[e_hdr->e_shstrndx].sh_offset + sect[s].sh_name));
i++;
}
s++;
}
return (PMODULEINFO)0;
return mod;
}
void* load_module(void* addr)
{
......@@ -83,6 +63,10 @@ void* load_module(void* addr)
}
return (void*)0;
}
void process_loop()
{
for(;;) asm("hlt");
}
void modules_init()
{
if((kernel_data.modules != 0) && (kernel_data.modules != kernel_data.modules_top)){
......@@ -101,4 +85,5 @@ void modules_init()
mod = (PMODULE)mod->next;
}
}
}
\ No newline at end of file
print("Modules loaded\n");
}
// PhoeniX OS Modules subsystem
// Copyright (C) 2013 PhoeniX
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef MODULES_H
#define MODULES_H
#include "pxlib.h"
#include "multiboot_info.h"
extern void modules_init();
extern void process_loop();
typedef struct {
struct {
long EI_MAG;
char EI_CLASS;
char EI_DATA;
char EI_VERSION;
char EI_OSABI;
char EI_ABIVERSION;
char EI_PAD;
char reserved[6];
} e_ident;
unsigned short e_type; /* Object file type */
unsigned short e_machine; /* Machine type */
unsigned long e_version; /* Object file version */
void* e_entry; /* Entry point address */
_uint64 e_phoff; /* Program header offset */
_uint64 e_shoff; /* Section header offset */
unsigned long e_flags; /* Processor-specific flags */
unsigned short e_ehsize; /* ELF header size */
unsigned short e_phentsize; /* Size of program header entry */
unsigned short e_phnum; /* Number of program header entries */
unsigned short e_shentsize; /* Size of section header entry */
unsigned short e_shnum; /* Number of section header entries */
unsigned short e_shstrndx; /* Section name string table index */
} ELF64HDR, *PELF64HDR;
typedef struct
{
unsigned long sh_name;
unsigned long sh_type;
_uint64 sh_flags;
_uint64 sh_addr;
_uint64 sh_offset;
_uint64 sh_size;