Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gdbserver
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
redox-os
gdbserver
Commits
2a3e9008
Verified
Commit
2a3e9008
authored
Aug 19, 2019
by
jD91mZM2
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bugfixes, still segfaults :(
parent
d95475a2
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
157 additions
and
39 deletions
+157
-39
src/main.rs
src/main.rs
+18
-0
src/os/linux.rs
src/os/linux.rs
+109
-28
src/os/mod.rs
src/os/mod.rs
+27
-10
test.c
test.c
+3
-1
No files found.
src/main.rs
View file @
2a3e9008
...
...
@@ -116,6 +116,24 @@ fn main() -> Result<()> {
}
CheckedPacket
::
from_data
(
Kind
::
Packet
,
out
)
},
Some
(
b
'X'
)
=>
{
let
data
=
&
packet
.data
[
1
..
];
let
sep1
=
memchr
::
memchr
(
b
','
,
&
data
)
.ok_or
(
"gdb didn't send a memory length"
)
?
;
let
(
addr
,
rest
)
=
data
.split_at
(
sep1
);
let
sep2
=
memchr
::
memchr
(
b
':'
,
&
rest
)
.ok_or
(
"gdb didn't send memory content"
)
?
;
let
(
_
,
content
)
=
rest
.split_at
(
sep2
);
let
addr
=
usize
::
from_str_radix
(
std
::
str
::
from_utf8
(
&
addr
)
?
,
16
)
?
;
// let len = usize::from_str_radix(std::str::from_utf8(&len[1..])?, 16)?;
let
mut
out
=
Vec
::
new
();
match
tracee
.setmem
(
&
content
[
1
..
],
addr
)
{
Ok
(())
=>
write!
(
out
,
"OK"
)
.unwrap
(),
Err
(
errno
)
=>
write!
(
out
,
"E{:02X}"
,
errno
)
.unwrap
(),
}
CheckedPacket
::
from_data
(
Kind
::
Packet
,
out
)
},
Some
(
b
'v'
)
=>
{
// if packet.data[1..].starts_with(b"Run") {
// let mut cursor = &packet.data[1..];
...
...
src/os/linux.rs
View file @
2a3e9008
...
...
@@ -35,6 +35,42 @@ macro_rules! ce {
}}
}
fn
getmem
<
G
,
E
>
(
mut
src
:
usize
,
dest
:
&
mut
[
u8
],
mut
get
:
G
)
->
Result
<
usize
,
E
>
where
G
:
FnMut
(
usize
)
->
Result
<
usize
,
E
>
{
for
chunk
in
dest
.chunks_mut
(
mem
::
size_of
::
<
usize
>
())
{
let
bytes
=
get
(
src
)
?
.to_ne_bytes
();
chunk
.copy_from_slice
(
&
bytes
[
..
chunk
.len
()]);
src
+=
mem
::
size_of
::
<
usize
>
();
}
Ok
(
dest
.len
())
}
fn
setmem
<
G
,
S
,
E
>
(
src
:
&
[
u8
],
mut
dest
:
usize
,
mut
get
:
G
,
mut
set
:
S
)
->
Result
<
(),
E
>
where
G
:
FnMut
(
usize
)
->
Result
<
usize
,
E
>
,
S
:
FnMut
(
usize
,
usize
)
->
Result
<
(),
E
>
,
{
let
mut
iter
=
src
.chunks_exact
(
mem
::
size_of
::
<
usize
>
());
for
chunk
in
iter
.by_ref
()
{
let
mut
bytes
=
[
0
;
mem
::
size_of
::
<
usize
>
()];
bytes
.copy_from_slice
(
chunk
);
let
word
=
usize
::
from_ne_bytes
(
bytes
);
set
(
dest
,
word
)
?
;
dest
+=
mem
::
size_of
::
<
usize
>
();
}
let
mut
bytes
=
get
(
dest
)
?
.to_ne_bytes
();
let
rest
=
iter
.remainder
();
bytes
[
..
rest
.len
()]
.copy_from_slice
(
rest
);
let
word
=
usize
::
from_ne_bytes
(
bytes
);
set
(
dest
,
word
)
?
;
Ok
(())
}
impl
super
::
Target
for
Os
{
fn
new
(
program
:
String
,
args
:
Vec
<
String
>
)
->
Result
<
Self
>
{
let
program
=
CString
::
new
(
program
)
?
.into_raw
();
...
...
@@ -233,47 +269,46 @@ impl super::Target for Os {
float
.xmm_space
[
14
]
=
registers
.xmm14
.map
(|
r
|
r
as
_
)
.unwrap_or
(
float
.xmm_space
[
14
]);
float
.xmm_space
[
15
]
=
registers
.xmm15
.map
(|
r
|
r
as
_
)
.unwrap_or
(
float
.xmm_space
[
15
]);
unsafe
{
ce!
(
libc
::
ptrace
(
libc
::
PTRACE_SETREGS
,
self
.pid
,
0
,
&
int
));
ce!
(
libc
::
ptrace
(
libc
::
PTRACE_SETFPREGS
,
self
.pid
,
0
,
&
float
));
}
Ok
(())
}
fn
getmem
(
&
mut
self
,
mut
src
:
usize
,
dest
:
&
mut
[
u8
])
->
Result
<
usize
,
i32
>
{
fn
getmem
(
&
mut
self
,
src
:
usize
,
dest
:
&
mut
[
u8
])
->
Result
<
usize
,
i32
>
{
// TODO: Don't report errors when able to read part of requested?
// Also implement this in the Redox kernel perhaps
for
dest
in
dest
.chunks_mut
(
mem
::
size_of
::
<
usize
>
())
{
unsafe
{
let
word
=
ce!
(
libc
::
ptrace
(
libc
::
PTRACE_PEEKDATA
,
self
.pid
,
src
));
let
bytes
=
word
.to_ne_bytes
();
dest
.copy_from_slice
(
&
bytes
[
..
dest
.len
()]);
src
+=
1
;
}
}
Ok
(
dest
.len
())
getmem
(
src
,
dest
,
|
addr
|
unsafe
{
Ok
(
ce!
(
libc
::
ptrace
(
libc
::
PTRACE_PEEKDATA
,
self
.pid
,
addr
))
as
usize
)
},
)
}
fn
setmem
(
&
mut
self
,
src
:
&
[
u8
],
mut
dest
:
usize
)
->
Result
<
(),
i32
>
{
for
src
in
src
.chunks
(
mem
::
size_of
::
<
usize
>
())
{
unsafe
{
let
word
=
ce!
(
libc
::
ptrace
(
libc
::
PTRACE_PEEKDATA
,
self
.pid
,
dest
));
let
mut
bytes
=
word
.to_ne_bytes
();
bytes
[
..
src
.len
()]
.copy_from_slice
(
src
);
dest
+=
1
;
let
word
=
usize
::
from_ne_bytes
(
bytes
);
libc
::
ptrace
(
libc
::
PTRACE_POKEDATA
,
self
.pid
,
dest
,
word
);
}
}
Ok
(())
fn
setmem
(
&
mut
self
,
src
:
&
[
u8
],
dest
:
usize
)
->
Result
<
(),
i32
>
{
println!
(
"Writing {:02X?} to address {:X}"
,
src
,
dest
);
setmem
(
src
,
dest
,
|
addr
|
unsafe
{
Ok
(
ce!
(
libc
::
ptrace
(
libc
::
PTRACE_PEEKDATA
,
self
.pid
,
addr
))
as
usize
)
},
|
addr
,
word
|
unsafe
{
ce!
(
libc
::
ptrace
(
libc
::
PTRACE_POKEDATA
,
self
.pid
,
addr
,
word
));
Ok
(())
}
)
}
fn
step
(
&
mut
self
,
signal
:
Option
<
u8
>
)
->
Result
<
u64
>
{
fn
step
(
&
mut
self
,
signal
:
Option
<
u8
>
)
->
Result
<
Option
<
u64
>
>
{
unsafe
{
re!
(
libc
::
ptrace
(
libc
::
PTRACE_SINGLESTEP
,
self
.pid
,
0
,
signal
.unwrap_or
(
0
)
as
libc
::
c_uint
));
re!
(
libc
::
waitpid
(
self
.pid
,
&
mut
self
.last_status
,
0
));
let
rip
=
re!
(
libc
::
ptrace
(
libc
::
PTRACE_PEEKUSER
,
self
.pid
,
libc
::
RIP
as
usize
*
mem
::
size_of
::
<
usize
>
()));
Ok
(
rip
as
u64
)
Ok
(
if
libc
::
WIFSTOPPED
(
self
.last_status
)
&&
libc
::
WSTOPSIG
(
self
.last_status
)
==
libc
::
SIGTRAP
{
let
rip
=
re!
(
libc
::
ptrace
(
libc
::
PTRACE_PEEKUSER
,
self
.pid
,
libc
::
RIP
as
usize
*
mem
::
size_of
::
<
usize
>
()));
Some
(
rip
as
u64
)
}
else
{
dbg!
(
self
.status
());
None
})
}
}
...
...
@@ -292,3 +327,49 @@ impl Drop for Os {
}
}
}
#[cfg(test)]
mod
tests
{
use
std
::{
cell
::
Cell
,
mem
,
};
#[test]
fn
getmem
()
{
const
SOURCE
:
&
[
u8
]
=
b
"testing one two three"
;
let
mut
dest
=
[
0
;
9
];
super
::
getmem
(
3
,
&
mut
dest
,
|
addr
|
->
Result
<
usize
,
()
>
{
let
mut
bytes
=
[
0
;
mem
::
size_of
::
<
usize
>
()];
bytes
.copy_from_slice
(
&
SOURCE
[
addr
..
addr
+
mem
::
size_of
::
<
usize
>
()]);
Ok
(
usize
::
from_ne_bytes
(
bytes
))
}
)
.unwrap
();
assert_eq!
(
&
dest
,
b
"ting one "
);
}
#[test]
fn
setmem
()
{
let
source
=
Cell
::
new
(
*
b
"testing one two three"
);
let
dest
=
b
"XXXXXXXXX"
;
super
::
setmem
(
dest
,
3
,
|
addr
|
->
Result
<
usize
,
()
>
{
let
mut
bytes
=
[
0
;
mem
::
size_of
::
<
usize
>
()];
bytes
.copy_from_slice
(
&
source
.get
()[
addr
..
addr
+
mem
::
size_of
::
<
usize
>
()]);
Ok
(
usize
::
from_ne_bytes
(
bytes
))
},
|
addr
,
word
|
->
Result
<
(),
()
>
{
let
mut
slice
=
source
.get
();
slice
[
addr
..
addr
+
mem
::
size_of
::
<
usize
>
()]
.copy_from_slice
(
&
word
.to_ne_bytes
());
source
.set
(
slice
);
Ok
(())
},
)
.unwrap
();
assert_eq!
(
&
source
.get
(),
b
"tesXXXXXXXXXtwo three"
);
}
}
src/os/mod.rs
View file @
2a3e9008
...
...
@@ -11,11 +11,32 @@ mod sys;
pub
use
regs
::
Registers
;
pub
use
sys
::
Os
;
#[derive(Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash)]
pub
enum
Status
{
Exited
(
i32
),
Signaled
(
i32
),
Stopped
(
i32
),
}
impl
Status
{
pub
fn
is_exited
(
&
self
)
->
bool
{
match
self
{
Status
::
Exited
(
_
)
=>
true
,
_
=>
false
}
}
pub
fn
is_signaled
(
&
self
)
->
bool
{
match
self
{
Status
::
Signaled
(
_
)
=>
true
,
_
=>
false
}
}
pub
fn
is_stopped
(
&
self
)
->
bool
{
match
self
{
Status
::
Stopped
(
_
)
=>
true
,
_
=>
false
}
}
}
pub
trait
Target
:
Sized
{
/// Spawn a new tracee and return a tracer for it
...
...
@@ -37,24 +58,20 @@ pub trait Target: Sized {
fn
setmem
(
&
mut
self
,
src
:
&
[
u8
],
dest
:
usize
)
->
Result
<
(),
i32
>
;
/// Single-step one instruction, return instruction pointer
fn
step
(
&
mut
self
,
signal
:
Option
<
u8
>
)
->
Result
<
u64
>
;
fn
step
(
&
mut
self
,
signal
:
Option
<
u8
>
)
->
Result
<
Option
<
u64
>
>
;
/// Resume execution while instruction pointer is inside the range
fn
resume
<
R
>
(
&
mut
self
,
range
:
R
)
->
Result
<
u64
>
fn
resume
<
R
>
(
&
mut
self
,
range
:
R
)
->
Result
<
()
>
where
R
:
RangeBounds
<
u64
>
{
let
mut
last
=
None
;
loop
{
let
rip
=
self
.step
(
None
)
?
;
println!
(
"{:X}"
,
rip
);
// Break if outside the range or if in what appears to be
// an infinite loop? Somehow this seems to sometimes occur
// and I don't know what it means
if
!
range
.contains
(
&
rip
)
||
last
==
Some
(
rip
)
{
break
Ok
(
rip
);
println!
(
"{:X?}"
,
rip
);
if
rip
.map
(|
rip
|
!
range
.contains
(
&
rip
))
.unwrap_or
(
true
)
{
break
;
}
last
=
Some
(
rip
);
}
Ok
(())
}
/// Continue execution until signal or other breakpoint
...
...
test.c
View file @
2a3e9008
...
...
@@ -2,5 +2,7 @@
#include <stdio.h>
int
main
()
{
printf
(
"Hello World
\n
"
);
for
(
int
i
=
0
;
i
<
5
;
++
i
)
{
puts
(
"Hello World"
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment