pub struct Object { /* private fields */ }Expand description
One object file or executable, independent of the format it is written in.
An object is a target, a kind, a list of Sections
(each carrying its own Relocations), and a list of Symbols. Executables also
have an entry point. The same object can be written in any format the crate supports;
reading a file returns an object of the same shape.
Nothing is checked while an object is built. validate checks
every rule the model has, and every writer runs it first, so a malformed object is an
error value, never a malformed file.
§Examples
A relocatable object with a function that calls an external one:
use object_lang::{
Architecture, Object, Relocation, RelocationTarget, Section, SectionKind, Symbol,
X86_64Reloc,
};
let mut obj = Object::relocatable(Architecture::X86_64);
// call puts; ret
let text = obj.add_section(
Section::new(".text", SectionKind::Text).with_data(vec![0xe8, 0, 0, 0, 0, 0xc3]),
);
obj.add_symbol(Symbol::function("main", text, 0, 6));
let puts = obj.add_symbol(Symbol::undefined("puts"));
obj.add_relocation(
text,
Relocation::new(1, X86_64Reloc::Plt32, RelocationTarget::Symbol(puts), -4),
)?;
let bytes = object_lang::elf::write(&obj)?;
let back = object_lang::elf::read(&bytes)?;
assert_eq!(back.symbols().len(), 2);
assert_eq!(back.sections()[0].relocations().len(), 1);Implementations§
Source§impl Object
impl Object
Sourcepub const fn new(kind: FileKind, arch: Architecture) -> Self
pub const fn new(kind: FileKind, arch: Architecture) -> Self
Creates an empty object of the given kind for the given architecture.
The entry point starts at zero and the stack is not executable.
§Examples
use object_lang::{Architecture, FileKind, Object};
let exe = Object::new(FileKind::Executable, Architecture::Aarch64);
assert_eq!(exe.architecture(), Architecture::Aarch64);
assert!(exe.sections().is_empty());Sourcepub const fn relocatable(arch: Architecture) -> Self
pub const fn relocatable(arch: Architecture) -> Self
Creates an empty relocatable object: Object::new(FileKind::Relocatable, arch).
§Examples
use object_lang::{Architecture, FileKind, Object};
assert_eq!(Object::relocatable(Architecture::X86_64).kind(), FileKind::Relocatable);Sourcepub const fn executable(arch: Architecture) -> Self
pub const fn executable(arch: Architecture) -> Self
Creates an empty executable: Object::new(FileKind::Executable, arch).
§Examples
use object_lang::{Architecture, FileKind, Object};
assert_eq!(Object::executable(Architecture::X86_64).kind(), FileKind::Executable);Sourcepub const fn kind(&self) -> FileKind
pub const fn kind(&self) -> FileKind
What the file is for.
§Examples
use object_lang::{Architecture, FileKind, Object};
assert_eq!(Object::executable(Architecture::X86_64).kind(), FileKind::Executable);Sourcepub const fn architecture(&self) -> Architecture
pub const fn architecture(&self) -> Architecture
The instruction set the object is built for.
§Examples
use object_lang::{Architecture, Object};
assert_eq!(Object::relocatable(Architecture::Aarch64).architecture(), Architecture::Aarch64);Sourcepub const fn entry(&self) -> u64
pub const fn entry(&self) -> u64
The address execution starts at. Meaningful for executables, where it must lie inside an executable section; relocatable objects normally leave it at zero.
§Examples
use object_lang::{Architecture, Object};
let mut exe = Object::executable(Architecture::X86_64);
exe.set_entry(0x40_1000);
assert_eq!(exe.entry(), 0x40_1000);Sourcepub const fn executable_stack(&self) -> bool
pub const fn executable_stack(&self) -> bool
Whether the program asks for an executable stack.
Almost nothing should: it is off by default. ELF records the request as a
.note.GNU-stack section in relocatable objects and a PT_GNU_STACK program
header in executables; when a file read in carries neither, it is reported as
true, because that is how the GNU toolchain and the Linux kernel treat a file
that does not say.
§Examples
use object_lang::{Architecture, Object};
let obj = Object::relocatable(Architecture::X86_64);
assert!(!obj.executable_stack());Sourcepub fn set_executable_stack(&mut self, executable: bool)
pub fn set_executable_stack(&mut self, executable: bool)
Sets whether the program asks for an executable stack. See
executable_stack.
§Examples
use object_lang::{Architecture, Object};
let mut obj = Object::relocatable(Architecture::X86_64);
obj.set_executable_stack(true);
assert!(obj.executable_stack());Sourcepub fn add_section(&mut self, section: Section) -> SectionId
pub fn add_section(&mut self, section: Section) -> SectionId
Adds a section and returns its id. Sections keep the order they were added in.
§Examples
use object_lang::{Architecture, Object, Section, SectionKind};
let mut obj = Object::relocatable(Architecture::X86_64);
let bss = obj.add_section(Section::new(".bss", SectionKind::Bss).with_bss_size(64));
assert_eq!(obj.section(bss).map(|s| s.size()), Some(64));Sourcepub fn sections(&self) -> &[Section]
pub fn sections(&self) -> &[Section]
Every section, in the order added; a SectionId indexes this slice.
§Examples
use object_lang::{Architecture, Object, Section, SectionKind};
let mut obj = Object::relocatable(Architecture::X86_64);
obj.add_section(Section::new(".text", SectionKind::Text));
assert_eq!(obj.sections()[0].name(), ".text");Sourcepub fn section(&self, id: SectionId) -> Option<&Section>
pub fn section(&self, id: SectionId) -> Option<&Section>
The section with this id, or None if the object has no such section.
§Examples
use object_lang::{Architecture, Object, Section, SectionKind};
let mut obj = Object::relocatable(Architecture::X86_64);
let id = obj.add_section(Section::new(".rodata", SectionKind::ReadOnlyData));
assert_eq!(obj.section(id).map(Section::name), Some(".rodata"));Sourcepub fn section_mut(&mut self, id: SectionId) -> Option<&mut Section>
pub fn section_mut(&mut self, id: SectionId) -> Option<&mut Section>
The section with this id, mutably, or None if the object has no such section.
§Examples
use object_lang::{Architecture, Object, Section, SectionKind};
let mut obj = Object::relocatable(Architecture::X86_64);
let text = obj.add_section(Section::new(".text", SectionKind::Text));
let offset = obj.section_mut(text).map(|s| s.append(&[0xc3], 16));
assert_eq!(offset, Some(Ok(0)));Sourcepub fn section_by_name(&self, name: &str) -> Option<SectionId>
pub fn section_by_name(&self, name: &str) -> Option<SectionId>
The first section with this name, or None. A linear search: formats allow
several sections to share a name, and this returns the earliest.
§Examples
use object_lang::{Architecture, Object, Section, SectionKind};
let mut obj = Object::relocatable(Architecture::X86_64);
let data = obj.add_section(Section::new(".data", SectionKind::Data));
assert_eq!(obj.section_by_name(".data"), Some(data));
assert_eq!(obj.section_by_name(".bss"), None);Sourcepub fn add_symbol(&mut self, symbol: Symbol) -> SymbolId
pub fn add_symbol(&mut self, symbol: Symbol) -> SymbolId
Adds a symbol and returns its id. Symbols keep the order they were added in; formats that need a different order (ELF puts local symbols first) reorder on write, so a file read back lists them in the format’s order.
§Examples
use object_lang::{Architecture, Object, Section, SectionKind, Symbol};
let mut obj = Object::relocatable(Architecture::X86_64);
let text = obj.add_section(Section::new(".text", SectionKind::Text).with_data(vec![0xc3]));
let f = obj.add_symbol(Symbol::function("f", text, 0, 1));
assert_eq!(obj.symbol(f).map(|s| s.name.as_str()), Some("f"));Sourcepub fn symbol(&self, id: SymbolId) -> Option<&Symbol>
pub fn symbol(&self, id: SymbolId) -> Option<&Symbol>
The symbol with this id, or None if the object has no such symbol.
§Examples
use object_lang::{Architecture, Object, Symbol};
let mut obj = Object::relocatable(Architecture::X86_64);
let id = obj.add_symbol(Symbol::undefined("exit"));
assert!(obj.symbol(id).is_some());Sourcepub fn symbol_mut(&mut self, id: SymbolId) -> Option<&mut Symbol>
pub fn symbol_mut(&mut self, id: SymbolId) -> Option<&mut Symbol>
The symbol with this id, mutably, or None if the object has no such symbol.
§Examples
use object_lang::{Architecture, Binding, Object, Symbol};
let mut obj = Object::relocatable(Architecture::X86_64);
let id = obj.add_symbol(Symbol::undefined("hook"));
if let Some(sym) = obj.symbol_mut(id) {
sym.binding = Binding::Weak;
}
assert_eq!(obj.symbols()[0].binding, Binding::Weak);Sourcepub fn symbol_by_name(&self, name: &str) -> Option<SymbolId>
pub fn symbol_by_name(&self, name: &str) -> Option<SymbolId>
The first symbol with this name, or None. A linear search.
§Examples
use object_lang::{Architecture, Object, Symbol};
let mut obj = Object::relocatable(Architecture::X86_64);
let id = obj.add_symbol(Symbol::undefined("memcpy"));
assert_eq!(obj.symbol_by_name("memcpy"), Some(id));Sourcepub fn add_relocation(
&mut self,
section: SectionId,
relocation: Relocation,
) -> Result<(), ModelError>
pub fn add_relocation( &mut self, section: SectionId, relocation: Relocation, ) -> Result<(), ModelError>
Adds a relocation to a section: shorthand for
object.section_mut(section)?.add_relocation(relocation).
The relocation itself is checked by validate, like
everything else.
§Errors
ModelError::UnknownSection if the object has no section section.
§Examples
use object_lang::{
Aarch64Reloc, Architecture, Object, Relocation, RelocationTarget, Section,
SectionKind, Symbol,
};
let mut obj = Object::relocatable(Architecture::Aarch64);
// bl <callee>
let text = obj.add_section(
Section::new(".text", SectionKind::Text).with_data(vec![0x00, 0x00, 0x00, 0x94]),
);
let callee = obj.add_symbol(Symbol::undefined("callee"));
obj.add_relocation(
text,
Relocation::new(0, Aarch64Reloc::Call26, RelocationTarget::Symbol(callee), 0),
)?;
assert_eq!(obj.sections()[0].relocations().len(), 1);Sourcepub fn validate(&self) -> Result<(), ModelError>
pub fn validate(&self) -> Result<(), ModelError>
Checks every rule of the model, returning the first violation.
Writers call this before writing anything, and readers call it on what they read,
so an object that passes is one every writer can represent (barring
format-specific limits, reported as WriteError). The rules
are listed under ModelError, SectionProblem,
SymbolProblem, and
RelocationProblem.
§Errors
The first rule the object breaks, as a ModelError.
§Examples
use object_lang::{
Architecture, ModelError, Object, Section, SectionKind, SectionProblem,
};
let mut obj = Object::relocatable(Architecture::X86_64);
let text = obj.add_section(Section::new(".text", SectionKind::Text).with_align(3));
assert_eq!(
obj.validate(),
Err(ModelError::Section { section: text, problem: SectionProblem::BadAlignment }),
);