From 7e9a242edb2744b6d8d6da7d7d36600e6bb9875f Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 21 Feb 2019 13:00:57 -0800 Subject: [PATCH] add alignment from decl through to elf --- src/artifact/decl.rs | 219 ++++++++++++++++++++++++------------------- src/elf.rs | 44 ++++----- 2 files changed, 145 insertions(+), 118 deletions(-) diff --git a/src/artifact/decl.rs b/src/artifact/decl.rs index 9eabcbe..19b1499 100644 --- a/src/artifact/decl.rs +++ b/src/artifact/decl.rs @@ -41,6 +41,39 @@ pub enum Scope { Weak, } +macro_rules! scope_methods { + () => { + /// Set scope to global + pub fn global(self) -> Self { + self.with_scope(Scope::Global) + } + /// Set scope to local + pub fn local(self) -> Self { + self.with_scope(Scope::Local) + } + /// Set scope to weak + pub fn weak(self) -> Self { + self.with_scope(Scope::Weak) + } + /// Builder for scope + pub fn with_scope(mut self, scope: Scope) -> Self { + self.scope = scope; + self + } + /// Gst scope + pub fn get_scope(&self) -> Scope { + self.scope + } + /// Set scope + pub fn set_scope(&mut self, scope: Scope) { + self.scope = scope; + } + /// Check if scope is `Scope::Global` + pub fn is_global(&self) -> bool { + self.scope == Scope::Global + } +}} + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] /// Linker visibility of a definition pub enum Visibility { @@ -54,6 +87,80 @@ pub enum Visibility { Hidden, } +macro_rules! visibility_methods { + () => { + /// Set visibility to default + pub fn default_visibility(self) -> Self { + self.with_visibility(Visibility::Default) + } + /// Set visibility to protected + pub fn protected(self) -> Self { + self.with_visibility(Visibility::Protected) + } + /// Set visibility to hidden + pub fn hidden(self) -> Self { + self.with_visibility(Visibility::Hidden) + } + /// Builder for visibility + pub fn with_visibility(mut self, visibility: Visibility) -> Self { + self.visibility =visibility; + self + } + /// Get visibility + pub fn get_visibility(&self) -> Visibility { + self.visibility + } + /// Set visibility + pub fn set_visibility(&mut self, visibility: Visibility) { + self.visibility = visibility; + } +}} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +/// Type of data declared +pub enum DataType { + /// Ordinary raw bytes + Bytes, + /// 0-terminated ascii string + String, +} + +macro_rules! datatype_methods { + () => { + /// Build datatype + pub fn with_datatype(mut self, datatype: DataType) -> Self { + self.datatype = datatype; + self + } + /// Set datatype + pub fn set_datatype(&mut self, datatype: DataType) { + self.datatype = datatype; + } + /// Get datatype + pub fn get_datatype(&self) -> DataType { + self.datatype + } + } +} + +macro_rules! align_methods { + () => { + /// Build alignment + pub fn with_align(mut self, align: Option) -> Self { + self.align = align; + self + } + /// Set alignment + pub fn set_align(&mut self, align: Option) { + self.align = align; + } + /// Get alignment + pub fn get_align(&self) -> Option { + self.align + } + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] /// A declaration that is defined inside this artifact pub enum DefinedDecl { @@ -103,9 +210,7 @@ impl DefinedDecl { pub fn is_writable(&self) -> bool { match self { DefinedDecl::Data(a) => a.is_writable(), - DefinedDecl::Function(_) | DefinedDecl::DebugSection(_) => { - false - } + DefinedDecl::Function(_) | DefinedDecl::DebugSection(_) => false, } } } @@ -275,73 +380,12 @@ impl Into for DataImportDecl { } } -macro_rules! scope_methods { - () => { - /// Set scope to global - pub fn global(self) -> Self { - self.with_scope(Scope::Global) - } - /// Set scope to local - pub fn local(self) -> Self { - self.with_scope(Scope::Local) - } - /// Set scope to weak - pub fn weak(self) -> Self { - self.with_scope(Scope::Weak) - } - /// Builder for scope - pub fn with_scope(mut self, scope: Scope) -> Self { - self.scope = scope; - self - } - /// Gst scope - pub fn get_scope(&self) -> Scope { - self.scope - } - /// Set scope - pub fn set_scope(&mut self, scope: Scope) { - self.scope = scope; - } - /// Check if scope is `Scope::Global` - pub fn is_global(&self) -> bool { - self.scope == Scope::Global - } -}} - -macro_rules! visibility_methods { - () => { - /// Set visibility to default - pub fn default_visibility(self) -> Self { - self.with_visibility(Visibility::Default) - } - /// Set visibility to protected - pub fn protected(self) -> Self { - self.with_visibility(Visibility::Protected) - } - /// Set visibility to hidden - pub fn hidden(self) -> Self { - self.with_visibility(Visibility::Hidden) - } - /// Builder for visibility - pub fn with_visibility(mut self, visibility: Visibility) -> Self { - self.visibility =visibility; - self - } - /// Get visibility - pub fn get_visibility(&self) -> Visibility { - self.visibility - } - /// Set visibility - pub fn set_visibility(&mut self, visibility: Visibility) { - self.visibility = visibility; - } -}} - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] /// Builder for function declarations pub struct FunctionDecl { scope: Scope, visibility: Visibility, + align: Option, } impl Default for FunctionDecl { @@ -349,6 +393,7 @@ impl Default for FunctionDecl { FunctionDecl { scope: Scope::Local, visibility: Visibility::Default, + align: None, } } } @@ -356,6 +401,7 @@ impl Default for FunctionDecl { impl FunctionDecl { scope_methods!(); visibility_methods!(); + align_methods!(); } impl Into for FunctionDecl { @@ -364,15 +410,6 @@ impl Into for FunctionDecl { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -/// Type of data declared -pub enum DataType { - /// Ordinary raw bytes - Bytes, - /// 0-terminated ascii string - String, -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] /// Builder for data declarations pub struct DataDecl { @@ -380,24 +417,7 @@ pub struct DataDecl { visibility: Visibility, writable: bool, datatype: DataType, -} - -macro_rules! datatype_methods { - () => { - /// Build datatype - pub fn with_datatype(mut self, datatype: DataType) -> Self { - self.datatype = datatype; - self - } - /// Set datatype - pub fn set_datatype(&mut self, datatype: DataType) { - self.datatype = datatype; - } - /// Get datatype - pub fn get_datatype(&self) -> DataType { - self.datatype - } - } + align: Option, } impl Default for DataDecl { @@ -407,6 +427,7 @@ impl Default for DataDecl { visibility: Visibility::Default, writable: false, datatype: DataType::Bytes, + align: None, } } } @@ -415,6 +436,7 @@ impl DataDecl { scope_methods!(); visibility_methods!(); datatype_methods!(); + align_methods!(); /// Set mutability to writable pub fn writable(mut self) -> Self { self.writable = true; @@ -429,7 +451,6 @@ impl DataDecl { pub fn is_writable(&self) -> bool { self.writable } - } impl Into for DataDecl { @@ -438,13 +459,16 @@ impl Into for DataDecl { } } - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] /// Builder for a debug section declaration -pub struct DebugSectionDecl { datatype: DataType } +pub struct DebugSectionDecl { + datatype: DataType, + align: Option, +} impl DebugSectionDecl { datatype_methods!(); + align_methods!(); /// Debug sections are never global, but we have an accessor /// for symmetry with other section declarations pub fn is_global(&self) -> bool { @@ -454,7 +478,10 @@ impl DebugSectionDecl { impl Default for DebugSectionDecl { fn default() -> Self { - DebugSectionDecl { datatype: DataType::Bytes } + DebugSectionDecl { + datatype: DataType::Bytes, + align: None, + } } } diff --git a/src/elf.rs b/src/elf.rs index c1ec2b4..bf8823d 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -201,6 +201,7 @@ struct SectionBuilder { alloc: bool, size: u64, name_offset: usize, + align: Option, } impl SectionBuilder { @@ -213,6 +214,7 @@ impl SectionBuilder { alloc: false, name_offset: 0, size, + align: None, } } /// Make this section executable @@ -230,6 +232,11 @@ impl SectionBuilder { self.write = writable; self } + /// Specify section alignment + pub fn align(mut self, align: Option) -> Self { + self.align = align; + self + } /// Set the byte offset of this section's name in the corresponding strtab pub fn name_offset(mut self, name_offset: usize) -> Self { @@ -257,36 +264,29 @@ impl SectionBuilder { if self.alloc { shdr.sh_flags |= SHF_ALLOC as u64 } + + let align = if let Some(align) = self.align { + align as u64 + } else if self.exec { + 0x10 + } else if self.write { + 0x8 + } else { + 1 + }; + match self.typ { SectionType::Bits => { - shdr.sh_addralign = if self.exec { - 0x10 - } else if self.write { - 0x8 - } else { - 1 - }; - shdr.sh_type = SHT_PROGBITS + shdr.sh_addralign = align; + shdr.sh_type = SHT_PROGBITS; } SectionType::String => { - shdr.sh_addralign = if self.exec { - 0x10 - } else if self.write { - 0x8 - } else { - 1 - }; + shdr.sh_addralign = align; shdr.sh_type = SHT_PROGBITS; shdr.sh_flags |= (SHF_MERGE | SHF_STRINGS) as u64; } SectionType::Data => { - shdr.sh_addralign = if self.exec { - 0x10 - } else if self.write { - 0x8 - } else { - 1 - }; + shdr.sh_addralign = align; shdr.sh_type = SHT_PROGBITS; } SectionType::StrTab => {