Skip to content

Commit

Permalink
Merge pull request m4b#2 from fastly/foote/latest-master
Browse files Browse the repository at this point in the history
Merge master with data linking fix
  • Loading branch information
jfoote authored Dec 11, 2017
2 parents 65051c7 + d272f87 commit 49e04ea
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 9 deletions.
13 changes: 9 additions & 4 deletions src/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub enum ArtifactError {
pub struct Prop {
pub global: bool,
pub function: bool,
pub writeable: bool,
pub cstring: bool,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
Expand All @@ -69,8 +71,10 @@ pub enum Decl {
DataImport,
/// A function defined in this artifact
Function { global: bool },
/// An data object defined in this artifact
Data { global: bool },
/// A data object defined in this artifact
Data { global: bool, writeable: bool },
/// A null-terminated string object defined in this artifact
CString { global: bool }
}

impl Decl {
Expand Down Expand Up @@ -262,8 +266,9 @@ impl Artifact {
match self.declarations.get(&decl_name) {
Some(ref stype) => {
let prop = match *stype {
&Decl::Data { global } => Prop { global, function: false },
&Decl::Function { global } => Prop { global, function: true },
&Decl::CString { global } => Prop { global, function: false, writeable: false, cstring: true },
&Decl::Data { global, writeable } => Prop { global, function: false, writeable, cstring: false },
&Decl::Function { global } => Prop { global, function: true, writeable: false, cstring: false},
_ if stype.is_import() => return Err(ArtifactError::ImportDefined(name.as_ref().to_string()).into()),
_ => unimplemented!("New Decl variant added but not covered in define method"),
};
Expand Down
4 changes: 2 additions & 2 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ fn run (args: Args) -> Result<(), Error> {
[
("deadbeef", Decl::Function { global: false }),
("main", Decl::Function { global: true }),
("str.1", Decl::Data { global: false }),
("str.1", Decl::CString { global: false }),
("DEADBEEF", Decl::DataImport),
("printf", Decl::FunctionImport),
].into_iter().cloned()
Expand Down Expand Up @@ -144,7 +144,7 @@ fn deadbeef (args: Args) -> Result<(), Error> {
// FIXME: need to state this isn't a string, but some linkers don't seem to care \o/
// gold complains though:
// ld.gold: warning: deadbeef.o: last entry in mergeable string section '.data.DEADBEEF' not null terminated
obj.declare("DEADBEEF", Decl::Data { global: true })?;
obj.declare("DEADBEEF", Decl::Data { global: true, writeable: false })?;
obj.define("DEADBEEF", [0xef, 0xbe, 0xad, 0xde].to_vec())?;
if args.mach {
obj.write::<Mach>(file)?;
Expand Down
28 changes: 25 additions & 3 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ impl SymbolBuilder {
/// The kind of section this can be; used in [SectionBuilder](struct.SectionBuilder.html)
pub enum SectionType {
Bits,
Data,
String,
StrTab,
SymTab,
Expand Down Expand Up @@ -174,6 +175,11 @@ impl SectionBuilder {
pub fn alloc(mut self) -> Self {
self.alloc = true; self
}
/// Make this section writeable
pub fn writeable(mut self, writeable:bool) -> Self {
self.write = writeable; self
}

/// Set the byte offset of this section's name in the corresponding strtab
pub fn name_offset(mut self, name_offset: usize) -> Self {
self.name_offset = name_offset; self
Expand Down Expand Up @@ -208,6 +214,10 @@ impl SectionBuilder {
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_type = SHT_PROGBITS;
}
SectionType::StrTab => {
shdr.sh_addralign = 0x1;
shdr.sh_type = SHT_STRTAB;
Expand Down Expand Up @@ -411,11 +421,22 @@ impl<'a> Elf<'a> {
self.symbols.insert(idx, symbol);
self.section_symbols.insert(idx, section_symbol);
// FIXME: probably add padding alignment

let mut section = {
let stype =
if prop.function {
SectionType::Bits
} else if prop.cstring {
SectionType::String
} else {
SectionType::Data
};

let tmp = SectionBuilder::new(size as u64)
.name_offset(section_offset)
.section_type(if prop.function { SectionType::Bits } else { SectionType::String })
.alloc();
.section_type(stype)
.alloc().writeable(prop.writeable);

// FIXME: I don't like this at all; can make exec() take bool but doesn't match other section properties
if prop.function { tmp.exec().create(&self.ctx) } else { tmp.create(&self.ctx) }
};
Expand Down Expand Up @@ -454,13 +475,14 @@ impl<'a> Elf<'a> {
// although we're not in the worst company here: https://github.com/ocaml/ocaml/pull/1330
Decl::Function {..} => (reloc::R_X86_64_PLT32, -4),
Decl::Data {..} => (reloc::R_X86_64_PC32, 0),
Decl::CString {..} => (reloc::R_X86_64_PC32, 0),
Decl::FunctionImport => (reloc::R_X86_64_PLT32, -4),
Decl::DataImport => (reloc::R_X86_64_GOTPCREL, -4),
}
};

let sym_idx = match *to_type {
Decl::Function {..} | Decl::Data {..} => to_idx + 2,
Decl::Function {..} | Decl::Data {..} | Decl::CString {..} => to_idx + 2,
// +2 for NOTYPE and FILE symbols
Decl::FunctionImport | Decl::DataImport => to_idx + self.section_symbols.len(),
// + section_symbols.len() because this is where the import symbols begin
Expand Down
1 change: 1 addition & 0 deletions src/mach.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ fn build_relocations(artifact: &Artifact, symtab: &SymbolTable) -> Relocations {
let reloc = match link.to.decl {
&Decl::Function {..} => X86_64_RELOC_BRANCH,
&Decl::Data {..} => X86_64_RELOC_SIGNED,
&Decl::CString {..} => X86_64_RELOC_SIGNED,
&Decl::FunctionImport => X86_64_RELOC_BRANCH,
&Decl::DataImport => X86_64_RELOC_GOT_LOAD,
};
Expand Down

0 comments on commit 49e04ea

Please sign in to comment.