Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
troll-rs
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
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
2xs
The Pip protokernel
troll-rs
Commits
5dbf5034
Commit
5dbf5034
authored
1 year ago
by
Michael Hauspie
Browse files
Options
Downloads
Patches
Plain Diff
Link should now work correctly
parent
7b5fadf5
No related branches found
No related tags found
1 merge request
!1
Add a new `link` subcommand
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/link.rs
+95
-6
95 additions, 6 deletions
src/link.rs
with
95 additions
and
6 deletions
src/link.rs
+
95
−
6
View file @
5dbf5034
...
...
@@ -21,8 +21,9 @@ use std::path::PathBuf;
// use pip_mpu_relocate::reloc::RelIter;
// use pip_mpu_relocate::relocate::relocate;
// use pip_mpu_relocate::symbols::SymbolsQuery;
use
std
::
io
::
Write
;
use
std
::
io
::
{
Buf
Write
r
,
Write
}
;
use
crate
::
rel_iter
::{
RelError
,
RelIter
};
use
crate
::
symbols
::
SymbolsIter
;
const
PADDING_SIZE
:
usize
=
32
;
...
...
@@ -97,7 +98,7 @@ fn align(value: usize, align: usize) -> usize {
/// `symbols_name` parameter.
///
/// An error is returned if *any* requested symbol is missing
pub
fn
export_user_info
<
'data
,
T
:
Write
,
E
:
EndianParse
>
(
fn
export_user_info
<
'data
,
T
:
Write
,
E
:
EndianParse
>
(
elf
:
&
'data
ElfBytes
<
'data
,
E
>
,
symbols_name
:
&
[
&
'static
str
],
output_file
:
&
mut
T
,
...
...
@@ -115,6 +116,40 @@ pub fn export_user_info<'data, T: Write, E: EndianParse>(
Ok
(())
}
/// Get the relocation values included in a given relocation section
///
/// It returns only relocation of type R_ARM_ABS32
fn
get_relocations_from_section
<
'data
,
E
:
EndianParse
>
(
elf
:
&
'data
ElfBytes
<
'data
,
E
>
,
section_name
:
&
str
,
)
->
Result
<
Option
<
Vec
<
u32
>>>
{
match
RelIter
::
new
(
&
elf
,
&
section_name
)
{
Ok
(
reliter
)
=>
Ok
(
Some
(
reliter
.filter
(|
rel
|
rel
.r_type
==
elf
::
abi
::
R_ARM_ABS32
)
.map
(|
rel
|
rel
.r_offset
as
u32
)
.collect
(),
)),
Err
(
RelError
::
SectionNotFound
)
=>
Ok
(
None
),
Err
(
e
)
=>
Err
(
anyhow!
(
"Error while extracting relocation information for {section_name}: {e}"
)),
}
}
/// Output a slice of u32 values to a file
fn
write_as_bytes
<
T
:
Write
>
(
values
:
&
[
u32
],
output
:
&
mut
T
)
->
Result
<
()
>
{
values
.iter
()
.map
(|
rel_offset
|
rel_offset
.to_le_bytes
())
.try_for_each
(|
bytes
|
output
.write_all
(
&
bytes
))
?
;
Ok
(())
}
/// Perform *pip* linking of the elf files and generate a binary image
/// of the firmware.
///
/// Parameters are given using an [`Opts`] object
pub
fn
link
(
opts
:
Opts
)
->
Result
<
()
>
{
// First, open and parse both crt0 and user_code elf files
...
...
@@ -124,7 +159,7 @@ pub fn link(opts: Opts) -> Result<()> {
let
user_code_elf_file
=
std
::
fs
::
read
(
&
opts
.user_code_elf
)
?
;
let
user_code_elf_data
=
user_code_elf_file
.as_slice
();
let
_
user_code_elf
=
elf
::
ElfBytes
::
<
AnyEndian
>
::
minimal_parse
(
user_code_elf_data
)
?
;
let
user_code_elf
=
elf
::
ElfBytes
::
<
AnyEndian
>
::
minimal_parse
(
user_code_elf_data
)
?
;
// Then open Pip elf file if necessary
let
pip_elf_data
=
match
opts
.pip_elf
{
...
...
@@ -138,7 +173,7 @@ pub fn link(opts: Opts) -> Result<()> {
};
// When reaching here, all files were opened and parsed
// we can safely open the output file
let
mut
output
=
std
::
fs
::
File
::
create
(
opts
.output
)
?
;
let
mut
output
=
BufWriter
::
new
(
std
::
fs
::
File
::
create
(
opts
.output
)
?
)
;
// First, if needed, output pip binary, padded to 32 bytes
if
let
Some
(
pip_elf
)
=
pip_elf
{
...
...
@@ -154,8 +189,62 @@ pub fn link(opts: Opts) -> Result<()> {
dump_sections
(
&
crt0_elf
,
CRT0_EXPORT_SECTIONS
,
&
mut
output
)
?
;
// Now, export the needed user code information
export_user_info
(
&
_user_code_elf
,
USER_CODE_INFO_SYMBOLS
,
&
mut
output
)
?
;
export_user_info
(
&
user_code_elf
,
USER_CODE_INFO_SYMBOLS
,
&
mut
output
)
?
;
// Dump .rom section in a vec
let
mut
rom_bytes
:
Vec
<
u8
>
=
vec!
[];
dump_sections
(
&
user_code_elf
,
&
[
".rom"
],
&
mut
rom_bytes
)
?
;
// Now the patch table for the .rom section (included in the .rel.rom section)
match
get_relocations_from_section
(
&
user_code_elf
,
".rel.rom"
)
?
{
Some
(
rom_relocation_offsets
)
=>
{
let
size
=
(
rom_relocation_offsets
.len
()
as
u32
)
.to_le_bytes
();
output
.write_all
(
&
size
)
?
;
write_as_bytes
(
&
rom_relocation_offsets
,
&
mut
output
)
?
;
// Use offsets to replace bytes that needs relocation by 0xff, and
// backup them in a values vec
let
mut
rom_relocation_values
:
Vec
<
u8
>
=
vec!
[];
rom_relocation_offsets
.iter
()
.enumerate
()
.try_for_each
(|(
offset_no
,
offset
)|
{
let
idx
:
usize
=
*
offset
as
usize
;
if
idx
>
rom_bytes
.len
()
-
4
{
return
Err
(
anyhow!
(
"Rom relocation offset {offset_no}({offset:0x}) points outside rom section ({} bytes long)"
,
rom_bytes
.len
()));
}
rom_relocation_values
.push
(
rom_bytes
[
idx
]);
rom_relocation_values
.push
(
rom_bytes
[
idx
+
1
]);
rom_relocation_values
.push
(
rom_bytes
[
idx
+
2
]);
rom_relocation_values
.push
(
rom_bytes
[
idx
+
3
]);
rom_bytes
[
idx
]
=
0xff
;
rom_bytes
[
idx
+
1
]
=
0xff
;
rom_bytes
[
idx
+
2
]
=
0xff
;
rom_bytes
[
idx
+
3
]
=
0xff
;
Ok
(())
})
?
;
// Now writes relocation values
output
.write_all
(
&
rom_relocation_values
)
?
;
}
None
=>
{
let
size
=
0u32
.to_le_bytes
();
output
.write_all
(
&
size
)
?
;
}
};
// Now the .rel.ram relocation offsets
match
get_relocations_from_section
(
&
user_code_elf
,
".rel.ram"
)
?
{
Some
(
ram_relocation_offsets
)
=>
{
let
size
=
(
ram_relocation_offsets
.len
()
as
u32
)
.to_le_bytes
();
output
.write_all
(
&
size
)
?
;
write_as_bytes
(
&
ram_relocation_offsets
,
&
mut
output
)
?
;
}
None
=>
{
let
size
=
0u32
.to_le_bytes
();
output
.write_all
(
&
size
)
?
;
}
};
// Finaly dump the patched .rom bytes
output
.write_all
(
&
rom_bytes
)
?
;
Ok
(())
}
...
...
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