-
Notifications
You must be signed in to change notification settings - Fork 57
Added name method to ElfSection #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
This commit introduces a problem with higher half kernels (such as mine) because it has to dereference a flat protected mode address to get the string table, instead of just giving that address to the caller like most do. A solution to this would be to add a closure in the arguments that maps a 32bit flat address to a 64bit correct address, but I'm not sure if this would make it too complicated to call. |
phil-opp
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for this PR! It's a very useful addition and it seems to work well. I've left a few suggestions, but besides that it looks good to me.
src/elf_sections.rs
Outdated
| } | ||
|
|
||
| impl ElfSection { | ||
| pub fn name(&self, tag: &ElfSectionsTag) -> &'static str { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it would be more natural the other way around:
impl ElfSectionsTag {
pub fn section_name(&self, section: &ElfSection) -> &'static str {…}
}
src/elf_sections.rs
Outdated
| &*(&tag.first_section as *const ElfSection).offset(tag.shndx as isize) | ||
| }; | ||
|
|
||
| let name_byte = (strtabs.addr + self.name as u64) as *const _; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, maybe we should find a better name for the name field (it's not the name but an index into the string table).
src/elf_sections.rs
Outdated
|
|
||
| let name_byte = (strtabs.addr + self.name as u64) as *const _; | ||
|
|
||
| unsafe { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This unsafe block is rather large. Maybe we could split it into two smaller blocks around name_byte.offset and from_utf8_unchecked?
src/elf_sections.rs
Outdated
| } | ||
| } | ||
|
|
||
| str::from_utf8_unchecked( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should use the safe from_utf8 instead? I'm not sure if the specification guarantees that the string is valid utf8… And even if it does, I think that the additional check is a good idea, because performance shouldn't really matter in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from_utf8_lossy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately String and Cow aren't available, because this crate is no_std.
|
Regarding higher half kernels: I'm not quite sure why this is a problem… All the pointers are relative to the multiboot header type, so it shouldn't be a problem to map it to a different address. Or am I missing something here? |
|
@phil-opp The |
|
Oh, I missed that. Hmm… An alternative solution could be to introduce a new impl ElfSectionsTag {
pub fn string_table(&self) -> &StringTable {
unsafe {
let string_table_ptr = (&tag.first_section as *const ElfSection).offset(tag.shndx as isize);
&*(string_table as *const StringTable)
}
}
}
struct StringTable([u8]);
impl StringTable {
pub fn section_name(&self, section: &ElfSection) -> &'static str {
let name_byte = self.0[section.name as usize];
// ...
unimplemented!();
}
}This way, you could adjust the reference returned by |
|
@phil-opp I think that it would be better to not use a DST for the string table as the elf64 specification does not have a specific size for it. Also an address cannot be casted to a DST pointer, as it also contains a length. The string table struct could possibly contain a byte pointer to the beginning of the string table, but without exposing this field to the caller it would defeat the purpose of having another struct. |
|
Hmm.. How about a |
|
This uses three small unsafe blocks instead of one large one, I'm not convinced that it is better though. If you have a better idea I'm happy to change it. |
phil-opp
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes! I've added some comments on how we could make the unsafe blocks smaller.
src/elf_sections.rs
Outdated
| unsafe { | ||
| str::from_utf8( | ||
| slice::from_raw_parts(name_ptr, strlen)).unwrap() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unsafe is only needed for from_raw_parts, so you could do
str::from_utf8(unsafe{slice::from_raw_parts(…) }).unwrap()
src/elf_sections.rs
Outdated
|
|
||
| impl StringTable { | ||
| pub fn section_name(&self, section: &ElfSection) -> &'static str { | ||
| unsafe fn strlen(start: *const u8) -> usize { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only *start.offset(i) is unsafe, so we could just do:
for i in 0.. {
if unsafe { *start.offset(i) } == 0 {
return i as usize;
}
}
unreachable!()This way it's much easier to spot the unsafe operations. On the other hand, I'm not comfortable with removing the unsafe from the strlen function (since it's not safe).
So I would prefer to remove the strlen function. Instead, we could do it like in your first commit:
let strlen;
for i in 0.. {
if unsafe { *start.offset(i) } == 0 {
strlen = i as usize;
break;
}
};Or alternatively with a while loop:
let strlen = {
let mut len = 0;
while unsafe { *start.offset(len) } != 0 {
len += 1;
}
len as usize
};|
Thanks a lot! 🎉 |
|
Pushed to crates.io as version |
|
No problem! It's nice to have another release. Any other features needed for the near future? |
|
None that I can think of… |
No description provided.