Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
K
kernel
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
redox-os
kernel
Commits
7c0b17d0
Commit
7c0b17d0
authored
8 years ago
by
Jeremy Soller
Browse files
Options
Downloads
Patches
Plain Diff
Load a very simple ELF and launch it in usermode
parent
4b98fb8c
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
elf.rs
+117
-15
117 additions, 15 deletions
elf.rs
lib.rs
+4
-1
4 additions, 1 deletion
lib.rs
with
121 additions
and
16 deletions
elf.rs
+
117
−
15
View file @
7c0b17d0
//! ELF executables
//! ELF executables
use
collections
::
{
String
,
Vec
}
;
use
collections
::
String
;
use
core
::
{
ptr
,
str
}
;
use
core
::
str
;
#[cfg(target_arch
=
"x86"
)]
#[cfg(target_arch
=
"x86"
)]
use
goblin
::
elf32
::{
header
,
program_header
};
use
goblin
::
elf32
::{
header
,
program_header
};
...
@@ -10,9 +10,15 @@ use goblin::elf32::{header, program_header};
...
@@ -10,9 +10,15 @@ use goblin::elf32::{header, program_header};
#[cfg(target_arch
=
"x86_64"
)]
#[cfg(target_arch
=
"x86_64"
)]
use
goblin
::
elf64
::{
header
,
program_header
};
use
goblin
::
elf64
::{
header
,
program_header
};
use
arch
::
externs
::{
memcpy
,
memset
};
use
arch
::
paging
::{
entry
,
ActivePageTable
,
Page
,
VirtualAddress
};
use
arch
::
start
::
usermode
;
use
arch
::
x86
::
tlb
;
/// An ELF executable
/// An ELF executable
pub
struct
Elf
<
'a
>
{
pub
struct
Elf
<
'a
>
{
pub
data
:
&
'a
[
u8
],
pub
data
:
&
'a
[
u8
],
header
:
&
'a
header
::
Header
}
}
impl
<
'a
>
Elf
<
'a
>
{
impl
<
'a
>
Elf
<
'a
>
{
...
@@ -25,29 +31,125 @@ impl<'a> Elf<'a> {
...
@@ -25,29 +31,125 @@ impl<'a> Elf<'a> {
}
else
if
data
.get
(
header
::
EI_CLASS
)
!=
Some
(
&
header
::
ELFCLASS
)
{
}
else
if
data
.get
(
header
::
EI_CLASS
)
!=
Some
(
&
header
::
ELFCLASS
)
{
Err
(
format!
(
"Elf: Invalid architecture: {:?} != {:?}"
,
data
.get
(
header
::
EI_CLASS
),
header
::
ELFCLASS
))
Err
(
format!
(
"Elf: Invalid architecture: {:?} != {:?}"
,
data
.get
(
header
::
EI_CLASS
),
header
::
ELFCLASS
))
}
else
{
}
else
{
Ok
(
Elf
{
data
:
data
})
Ok
(
Elf
{
data
:
data
,
header
:
unsafe
{
&*
(
data
.as_ptr
()
as
usize
as
*
const
header
::
Header
)
}
})
}
}
pub
fn
segments
(
&
'a
self
)
->
ElfSegments
<
'a
>
{
ElfSegments
{
data
:
self
.data
,
header
:
self
.header
,
i
:
0
}
}
}
}
pub
unsafe
fn
load_segments
(
&
self
)
->
Vec
<
program_header
::
ProgramHeader
>
{
/// Get the entry field of the header
let
mut
segments
=
Vec
::
new
();
pub
fn
entry
(
&
self
)
->
usize
{
self
.header.e_entry
as
usize
}
/// Test function to run. Remove and replace with proper syscall
pub
fn
run
(
self
)
{
let
mut
active_table
=
unsafe
{
ActivePageTable
::
new
()
};
for
segment
in
self
.segments
()
{
println!
(
"Segment {:X} flags {:X} off {:X} virt {:X} phys {:X} file {} mem {} align {}"
,
segment
.p_type
,
segment
.p_flags
,
segment
.p_offset
,
segment
.p_vaddr
,
segment
.p_paddr
,
segment
.p_filesz
,
segment
.p_memsz
,
segment
.p_align
);
if
segment
.p_type
==
program_header
::
PT_LOAD
{
let
start_page
=
Page
::
containing_address
(
VirtualAddress
::
new
(
segment
.p_vaddr
as
usize
));
let
end_page
=
Page
::
containing_address
(
VirtualAddress
::
new
((
segment
.p_vaddr
+
segment
.p_memsz
)
as
usize
));
for
page
in
Page
::
range_inclusive
(
start_page
,
end_page
)
{
active_table
.map
(
page
,
entry
::
NO_EXECUTE
|
entry
::
WRITABLE
);
}
unsafe
{
// Update the page table
tlb
::
flush_all
();
// Copy file data
memcpy
(
segment
.p_vaddr
as
*
mut
u8
,
(
self
.data
.as_ptr
()
as
usize
+
segment
.p_offset
as
usize
)
as
*
const
u8
,
segment
.p_filesz
as
usize
);
// Set BSS
memset
((
segment
.p_vaddr
+
segment
.p_filesz
)
as
*
mut
u8
,
0
,
(
segment
.p_memsz
-
segment
.p_filesz
)
as
usize
);
}
let
mut
flags
=
entry
::
NO_EXECUTE
|
entry
::
USER_ACCESSIBLE
;
let
header
=
&*
(
self
.data
.as_ptr
()
as
usize
as
*
const
header
::
Header
);
if
segment
.p_flags
&
program_header
::
PF_R
==
program_header
::
PF_R
{
flags
.insert
(
entry
::
PRESENT
);
}
for
i
in
0
..
header
.e_phnum
{
// W ^ X. If it is executable, do not allow it to be writable, even if requested
let
segment
=
ptr
::
read
((
self
.data
.as_ptr
()
as
usize
+
header
.e_phoff
as
usize
+
i
as
usize
*
header
.e_phentsize
as
usize
)
as
*
const
program_header
::
ProgramHeader
);
if
segment
.p_flags
&
program_header
::
PF_X
==
program_header
::
PF_X
{
flags
.remove
(
entry
::
NO_EXECUTE
);
}
else
if
segment
.p_flags
&
program_header
::
PF_W
==
program_header
::
PF_W
{
flags
.insert
(
entry
::
WRITABLE
);
}
if
segment
.p_type
==
program_header
::
PT_LOAD
||
segment
.p_type
==
program_header
::
PT_TLS
{
for
page
in
Page
::
range_inclusive
(
start_page
,
end_page
)
{
segments
.push
(
segment
);
println!
(
"{:X}: {:?}"
,
page
.start_address
()
.get
(),
flags
);
active_table
.remap
(
page
,
flags
);
}
unsafe
{
// Update the page table
tlb
::
flush_all
();
}
}
}
}
}
segments
unsafe
{
// Map stack
let
start_page
=
Page
::
containing_address
(
VirtualAddress
::
new
(
0x80000000
));
let
end_page
=
Page
::
containing_address
(
VirtualAddress
::
new
(
0x80000000
+
64
*
1024
-
1
));
for
page
in
Page
::
range_inclusive
(
start_page
,
end_page
)
{
active_table
.map
(
page
,
entry
::
NO_EXECUTE
|
entry
::
WRITABLE
|
entry
::
USER_ACCESSIBLE
);
}
// Update the page table
tlb
::
flush_all
();
// Clear stack
memset
(
0x80000000
as
*
mut
u8
,
0
,
64
*
1024
);
// Go to usermode
usermode
(
self
.entry
(),
0x80000000
+
64
*
1024
-
256
);
}
}
}
}
/// Get the entry field of the header
pub
struct
ElfSegments
<
'a
>
{
pub
unsafe
fn
entry
(
&
self
)
->
usize
{
data
:
&
'a
[
u8
],
let
header
=
&*
(
self
.data
.as_ptr
()
as
usize
as
*
const
header
::
Header
);
header
:
&
'a
header
::
Header
,
header
.e_entry
as
usize
i
:
usize
}
impl
<
'a
>
Iterator
for
ElfSegments
<
'a
>
{
type
Item
=
&
'a
program_header
::
ProgramHeader
;
fn
next
(
&
mut
self
)
->
Option
<
Self
::
Item
>
{
if
self
.i
<
self
.header.e_phnum
as
usize
{
let
item
=
unsafe
{
&*
((
self
.data
.as_ptr
()
as
usize
+
self
.header.e_phoff
as
usize
+
self
.i
*
self
.header.e_phentsize
as
usize
)
as
*
const
program_header
::
ProgramHeader
)
};
self
.i
+=
1
;
Some
(
item
)
}
else
{
None
}
}
}
}
}
This diff is collapsed.
Click to expand it.
lib.rs
+
4
−
1
View file @
7c0b17d0
...
@@ -133,6 +133,9 @@ pub extern fn kmain() {
...
@@ -133,6 +133,9 @@ pub extern fn kmain() {
let
pid
=
syscall
::
getpid
();
let
pid
=
syscall
::
getpid
();
println!
(
"BSP: {:?}"
,
pid
);
println!
(
"BSP: {:?}"
,
pid
);
let
elf
=
elf
::
Elf
::
from
(
include_bytes!
(
"../init/main"
))
.expect
(
"could not load elf"
);
elf
.run
();
/*
/*
if let Ok(_context_lock) = context::contexts_mut().spawn(context_test) {
if let Ok(_context_lock) = context::contexts_mut().spawn(context_test) {
print!("Spawned context\n");
print!("Spawned context\n");
...
@@ -143,7 +146,7 @@ pub extern fn kmain() {
...
@@ -143,7 +146,7 @@ pub extern fn kmain() {
print!("Main halt\n");
print!("Main halt\n");
*/
*/
loop
{
loop
{
unsafe
{
interrupt
::
enable_and_halt
();
}
unsafe
{
interrupt
::
enable_and_halt
();
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment