Skip to content
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

elf: improve attributes section support #525

Merged
merged 1 commit into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 45 additions & 34 deletions crates/examples/src/bin/elfcopy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
let mut in_versym = None;
let mut in_verdef = None;
let mut in_verneed = None;
let mut in_attrib = None;
let mut in_attributes = None;
let mut out_sections = Vec::with_capacity(in_sections.len());
let mut out_sections_index = Vec::with_capacity(in_sections.len());
for (i, in_section) in in_sections.iter().enumerate() {
Expand Down Expand Up @@ -268,8 +268,8 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
index = writer.reserve_gnu_verneed_section_index();
}
elf::SHT_GNU_ATTRIBUTES => {
in_attrib = in_section.gnu_attributes(endian, in_data)?;
debug_assert!(in_attrib.is_some());
in_attributes = in_section.gnu_attributes(endian, in_data)?;
debug_assert!(in_attributes.is_some());
index = writer.reserve_gnu_attributes_section_index();
}
other => {
Expand Down Expand Up @@ -434,24 +434,40 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
}
}

// Add one byte for the version field at the start of the section
let mut gnu_attributes_size = 1;
// We will cache all of our attribute data here for later
let mut gnu_attrib_vendor_sections = Vec::new();
if let Some(mut vsections) = in_attrib.clone() {
while let Some((vendor_name, mut tags)) = vsections.next()? {
let mut subsection = Vec::new();
let mut subsection_length = 0;
while let Some((tag, attrib_data)) = tags.next()? {
// Add the size of our tag (1-byte) + the size of the size field (4-bytes)
// plus the size of the sub-section data
subsection_length += 5 + attrib_data.len() as u32;
subsection.push((tag, attrib_data.clone()));
}
// Add the length of our size field + the length of the vendor string + the null byte
gnu_attributes_size += subsection_length as usize + 4 + vendor_name.len() + 1;
gnu_attrib_vendor_sections.push((vendor_name, subsection_length, subsection));
let mut gnu_attributes = Vec::new();
if let Some(attributes) = in_attributes {
let mut writer = writer.attributes_writer();
let mut subsections = attributes.subsections()?;
while let Some(subsection) = subsections.next()? {
writer.start_subsection(subsection.vendor());
let mut subsubsections = subsection.subsubsections();
while let Some(subsubsection) = subsubsections.next()? {
writer.start_subsubsection(subsubsection.tag());
match subsubsection.tag() {
elf::Tag_File => {}
elf::Tag_Section => {
let mut indices = subsubsection.indices();
while let Some(index) = indices.next()? {
writer.write_subsubsection_index(out_sections_index[index as usize].0);
}
writer.write_subsubsection_index(0);
}
elf::Tag_Symbol => {
let mut indices = subsubsection.indices();
while let Some(index) = indices.next()? {
writer.write_subsubsection_index(out_syms_index[index as usize].0);
}
writer.write_subsubsection_index(0);
}
_ => unimplemented!(),
}
writer.write_subsubsection_attributes(subsubsection.attributes_data());
writer.end_subsubsection();
}
writer.end_subsection();
}
gnu_attributes = writer.data();
assert_ne!(gnu_attributes.len(), 0);
}

// Start reserving file ranges.
Expand All @@ -465,7 +481,6 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
let mut dynamic_addr = 0;
let mut dynsym_addr = 0;
let mut dynstr_addr = 0;
let mut attributes_addr = 0;

let mut alloc_sections = Vec::new();
if in_segments.is_empty() {
Expand All @@ -478,6 +493,9 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
in_section.sh_addralign(endian).into() as usize,
);
}
elf::SHT_GNU_ATTRIBUTES => {
writer.reserve_gnu_attributes(gnu_attributes.len());
}
_ => {}
}
}
Expand Down Expand Up @@ -570,8 +588,7 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
);
}
elf::SHT_GNU_ATTRIBUTES => {
attributes_addr = in_section.sh_addr(endian).into();
writer.reserve_gnu_attributes(gnu_attributes_size);
writer.reserve_gnu_attributes(gnu_attributes.len());
}
_ => {}
}
Expand Down Expand Up @@ -621,6 +638,9 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
debug_assert_eq!(out_sections[i].offset, writer.len());
writer.write(in_section.data(endian, in_data)?);
}
elf::SHT_GNU_ATTRIBUTES => {
writer.write_gnu_attributes(&gnu_attributes);
}
_ => {}
}
}
Expand Down Expand Up @@ -806,16 +826,7 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
writer.write(in_section.data(endian, in_data)?);
}
elf::SHT_GNU_ATTRIBUTES => {
writer.write_align_gnu_attributes();
writer.write_gnu_attributes_version();
for (vendor_name, section_length, subsections) in
gnu_attrib_vendor_sections.iter()
{
writer.write_gnu_attributes_subsection(*section_length, vendor_name);
for (tag, tag_data) in subsections.iter() {
writer.write_gnu_attributes_subsubsection(*tag, tag_data);
}
}
writer.write_gnu_attributes(&gnu_attributes);
}
_ => {}
}
Expand Down Expand Up @@ -979,7 +990,7 @@ fn copy_file<Elf: FileHeader<Endian = Endianness>>(
writer.write_gnu_verneed_section_header(verneed_addr);
}
elf::SHT_GNU_ATTRIBUTES => {
writer.write_gnu_attributes_section_header(attributes_addr);
writer.write_gnu_attributes_section_header();
}
other => {
panic!("Unsupported section type {:x}", other);
Expand Down
35 changes: 35 additions & 0 deletions crates/examples/src/readobj/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ fn print_section_headers<Elf: FileHeader>(
SHT_GNU_VERDEF => print_gnu_verdef(p, endian, data, elf, sections, section),
SHT_GNU_VERNEED => print_gnu_verneed(p, endian, data, elf, sections, section),
SHT_GNU_VERSYM => print_gnu_versym(p, endian, data, elf, sections, section),
// TODO: other sections that contain attributes
SHT_GNU_ATTRIBUTES => print_attributes(p, endian, data, elf, section),
// TODO:
//SHT_SHLIB =>
//SHT_INIT_ARRAY =>
Expand Down Expand Up @@ -781,6 +783,38 @@ fn print_gnu_versym<Elf: FileHeader>(
}
}

fn print_attributes<Elf: FileHeader>(
p: &mut Printer<'_>,
endian: Elf::Endian,
data: &[u8],
_elf: &Elf,
section: &Elf::SectionHeader,
) {
if let Some(section) = section.attributes(endian, data).print_err(p) {
p.group("Attributes", |p| {
p.field("Version", section.version());
if let Some(mut subsections) = section.subsections().print_err(p) {
while let Some(Some(subsection)) = subsections.next().print_err(p) {
p.group("Subsection", |p| {
p.field_inline_string("Vendor", subsection.vendor());
let mut subsubsections = subsection.subsubsections();
while let Some(Some(subsubsection)) = subsubsections.next().print_err(p) {
p.group("Subsubsection", |p| {
p.field_enum("Tag", subsubsection.tag(), FLAGS_TAG);
let mut indices = subsubsection.indices();
while let Some(Some(index)) = indices.next().print_err(p) {
p.field("Index", index);
}
// TODO: print attributes
});
}
});
}
}
});
}
}

fn print_version<Elf: FileHeader>(
p: &mut Printer<'_>,
versions: Option<&VersionTable<Elf>>,
Expand Down Expand Up @@ -3303,3 +3337,4 @@ static FLAGS_DF_1: &[Flag<u32>] = &flags!(
static FLAGS_VER_FLG: &[Flag<u16>] = &flags!(VER_FLG_BASE, VER_FLG_WEAK);
static FLAGS_VER_NDX: &[Flag<u16>] = &flags!(VER_NDX_LOCAL, VER_NDX_GLOBAL);
static FLAGS_VERSYM: &[Flag<u16>] = &flags!(VERSYM_HIDDEN);
static FLAGS_TAG: &[Flag<u8>] = &flags!(Tag_File, Tag_Section, Tag_Symbol);
9 changes: 9 additions & 0 deletions crates/examples/testfiles/elf/base-mips64el.o.readobj
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@ SectionHeader {
Info: 0
AddressAlign: 0x1
EntrySize: 0x0
Attributes {
Version: 65
Subsection {
Vendor: "gnu"
Subsubsection {
Tag: Tag_File (0x1)
}
}
}
}
SectionHeader {
Index: 13
Expand Down
9 changes: 9 additions & 0 deletions crates/examples/testfiles/elf/base-mips64el.readobj
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,15 @@ SectionHeader {
Info: 0
AddressAlign: 0x1
EntrySize: 0x0
Attributes {
Version: 65
Subsection {
Vendor: "gnu"
Subsubsection {
Tag: Tag_File (0x1)
}
}
}
}
SectionHeader {
Index: 28
Expand Down
7 changes: 7 additions & 0 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6724,6 +6724,13 @@ pub const R_XTENSA_NDIFF16: u32 = 61;
#[allow(missing_docs)]
pub const R_XTENSA_NDIFF32: u32 = 62;

#[allow(missing_docs, non_upper_case_globals)]
pub const Tag_File: u8 = 1;
#[allow(missing_docs, non_upper_case_globals)]
pub const Tag_Section: u8 = 2;
#[allow(missing_docs, non_upper_case_globals)]
pub const Tag_Symbol: u8 = 3;

unsafe_impl_endian_pod!(
FileHeader32,
FileHeader64,
Expand Down
Loading