mirror of
https://github.com/encounter/object.git
synced 2026-07-10 12:18:39 -07:00
Rework internal symbol layout; support local records
This commit is contained in:
+5
-10
@@ -92,7 +92,7 @@ pub mod record_type {
|
||||
pub const VENDEXT: u8 = 0xCE;
|
||||
}
|
||||
|
||||
/// OMF record header - common to all record types
|
||||
/// OMF record header
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct RecordHeader {
|
||||
@@ -195,7 +195,7 @@ pub enum FrameMethod {
|
||||
}
|
||||
|
||||
/// Check if a byte is a valid OMF record type
|
||||
pub fn is_omf_record_type(byte: u8) -> bool {
|
||||
pub(crate) fn is_omf_record_type(byte: u8) -> bool {
|
||||
use record_type::*;
|
||||
matches!(
|
||||
byte,
|
||||
@@ -242,13 +242,8 @@ pub fn is_omf_record_type(byte: u8) -> bool {
|
||||
)
|
||||
}
|
||||
|
||||
/// Check if a record type uses 32-bit fields
|
||||
pub fn is_32bit_record(record_type: u8) -> bool {
|
||||
record_type & 0x01 != 0
|
||||
}
|
||||
|
||||
/// Helper to read an OMF index (1 or 2 bytes)
|
||||
pub fn read_index(data: &[u8]) -> Option<(u16, usize)> {
|
||||
pub(crate) fn read_index(data: &[u8]) -> Option<(u16, usize)> {
|
||||
if data.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -268,7 +263,7 @@ pub fn read_index(data: &[u8]) -> Option<(u16, usize)> {
|
||||
}
|
||||
|
||||
/// Helper to read a counted string (length byte followed by string)
|
||||
pub fn read_counted_string(data: &[u8]) -> Option<(&[u8], usize)> {
|
||||
pub(crate) fn read_counted_string(data: &[u8]) -> Option<(&[u8], usize)> {
|
||||
if data.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -283,7 +278,7 @@ pub fn read_counted_string(data: &[u8]) -> Option<(&[u8], usize)> {
|
||||
|
||||
/// Read an encoded value (used in LIDATA for repeat counts and block counts)
|
||||
/// Returns the value and number of bytes consumed
|
||||
pub fn read_encoded_value(data: &[u8]) -> Option<(u32, usize)> {
|
||||
pub(crate) fn read_encoded_value(data: &[u8]) -> Option<(u32, usize)> {
|
||||
if data.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1193,7 +1193,7 @@ where
|
||||
),
|
||||
),
|
||||
#[cfg(feature = "omf")]
|
||||
Omf((omf::OmfSymbolIterator<'data, 'file>, PhantomData<R>)),
|
||||
Omf((omf::OmfSymbolIterator<'data, 'file, R>, PhantomData<R>)),
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'file, R> {
|
||||
|
||||
+27
-238
@@ -1,13 +1,15 @@
|
||||
//! OMF file implementation for the unified read API.
|
||||
|
||||
use crate::read::{
|
||||
self, Architecture, ByteString, ComdatKind, Error, Export, FileFlags, Import,
|
||||
NoDynamicRelocationIterator, Object, ObjectComdat, ObjectKind, ObjectSection, ObjectSegment,
|
||||
ReadRef, Result, SectionIndex, SegmentFlags, SymbolIndex,
|
||||
Architecture, ByteString, Error, Export, FileFlags, Import, NoDynamicRelocationIterator,
|
||||
Object, ObjectKind, ObjectSection, ReadRef, Result, SectionIndex, SymbolIndex,
|
||||
};
|
||||
use crate::SubArchitecture;
|
||||
|
||||
use super::{OmfFile, OmfSection, OmfSymbol, OmfSymbolIterator, OmfSymbolTable};
|
||||
use super::{
|
||||
OmfComdat, OmfComdatIterator, OmfFile, OmfSection, OmfSectionIterator, OmfSegmentIterator,
|
||||
OmfSegmentRef, OmfSymbol, OmfSymbolIterator, OmfSymbolTable,
|
||||
};
|
||||
|
||||
impl<'data, R: ReadRef<'data>> Object<'data> for OmfFile<'data, R> {
|
||||
type Segment<'file>
|
||||
@@ -46,7 +48,7 @@ impl<'data, R: ReadRef<'data>> Object<'data> for OmfFile<'data, R> {
|
||||
Self: 'file,
|
||||
'data: 'file;
|
||||
type SymbolIterator<'file>
|
||||
= OmfSymbolIterator<'data, 'file>
|
||||
= OmfSymbolIterator<'data, 'file, R>
|
||||
where
|
||||
Self: 'file,
|
||||
'data: 'file;
|
||||
@@ -127,26 +129,15 @@ impl<'data, R: ReadRef<'data>> Object<'data> for OmfFile<'data, R> {
|
||||
|
||||
fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol<'_>> {
|
||||
let idx = index.0;
|
||||
let total_publics = self.publics.len();
|
||||
let total_externals = self.externals.len();
|
||||
let total_before_communals = total_publics + total_externals;
|
||||
|
||||
if idx < total_publics {
|
||||
Ok(self.publics[idx].clone())
|
||||
} else if idx < total_before_communals {
|
||||
Ok(self.externals[idx - total_publics].clone())
|
||||
} else if idx < total_before_communals + self.communals.len() {
|
||||
Ok(self.communals[idx - total_before_communals].clone())
|
||||
} else {
|
||||
Err(Error("Symbol index out of bounds"))
|
||||
if idx >= self.symbols.len() {
|
||||
return Err(Error("Symbol index out of bounds"));
|
||||
}
|
||||
Ok(self.symbols[idx].clone())
|
||||
}
|
||||
|
||||
fn symbols(&self) -> Self::SymbolIterator<'_> {
|
||||
OmfSymbolIterator {
|
||||
publics: &self.publics,
|
||||
externals: &self.externals,
|
||||
communals: &self.communals,
|
||||
file: self,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
@@ -157,10 +148,8 @@ impl<'data, R: ReadRef<'data>> Object<'data> for OmfFile<'data, R> {
|
||||
|
||||
fn dynamic_symbols(&self) -> Self::SymbolIterator<'_> {
|
||||
OmfSymbolIterator {
|
||||
publics: &[],
|
||||
externals: &[],
|
||||
communals: &[],
|
||||
index: 0,
|
||||
file: self,
|
||||
index: usize::MAX, // Empty iterator
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,10 +162,18 @@ impl<'data, R: ReadRef<'data>> Object<'data> for OmfFile<'data, R> {
|
||||
}
|
||||
|
||||
fn imports(&self) -> Result<alloc::vec::Vec<Import<'data>>> {
|
||||
// External symbols are imports in OMF
|
||||
// Only true external symbols are imports in OMF
|
||||
// LocalExternal (LEXTDEF) are module-local references that should be resolved
|
||||
// within the same module by LocalPublic (LPUBDEF) symbols
|
||||
Ok(self
|
||||
.externals
|
||||
.all_symbols()
|
||||
.iter()
|
||||
.filter(|sym| {
|
||||
matches!(
|
||||
sym.class,
|
||||
super::OmfSymbolClass::External | super::OmfSymbolClass::ComdatExternal
|
||||
)
|
||||
})
|
||||
.map(|ext| Import {
|
||||
library: ByteString(b""),
|
||||
name: ByteString(ext.name),
|
||||
@@ -185,10 +182,12 @@ impl<'data, R: ReadRef<'data>> Object<'data> for OmfFile<'data, R> {
|
||||
}
|
||||
|
||||
fn exports(&self) -> Result<alloc::vec::Vec<Export<'data>>> {
|
||||
// Public symbols are exports in OMF
|
||||
// Only true public symbols are exports in OMF
|
||||
// LocalPublic (LPUBDEF) are module-local symbols not visible outside
|
||||
Ok(self
|
||||
.publics
|
||||
.all_symbols()
|
||||
.iter()
|
||||
.filter(|sym| sym.class == super::OmfSymbolClass::Public)
|
||||
.map(|pub_sym| Export {
|
||||
name: ByteString(pub_sym.name),
|
||||
address: pub_sym.offset as u64,
|
||||
@@ -232,213 +231,3 @@ impl<'data, R: ReadRef<'data>> Object<'data> for OmfFile<'data, R> {
|
||||
FileFlags::None
|
||||
}
|
||||
}
|
||||
|
||||
/// An OMF segment reference.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfSegmentRef<'data, 'file, R: ReadRef<'data>> {
|
||||
file: &'file OmfFile<'data, R>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for OmfSegmentRef<'data, 'file, R> {}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for OmfSegmentRef<'data, 'file, R> {
|
||||
fn address(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
fn size(&self) -> u64 {
|
||||
self.file.segments[self.index].length as u64
|
||||
}
|
||||
|
||||
fn align(&self) -> u64 {
|
||||
match self.file.segments[self.index].alignment {
|
||||
crate::omf::SegmentAlignment::Byte => 1,
|
||||
crate::omf::SegmentAlignment::Word => 2,
|
||||
crate::omf::SegmentAlignment::Paragraph => 16,
|
||||
crate::omf::SegmentAlignment::Page => 256,
|
||||
crate::omf::SegmentAlignment::DWord => 4,
|
||||
crate::omf::SegmentAlignment::Page4K => 4096,
|
||||
_ => 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn file_range(&self) -> (u64, u64) {
|
||||
(0, 0)
|
||||
}
|
||||
|
||||
fn data(&self) -> Result<&'data [u8]> {
|
||||
// OMF segments don't have direct file mapping
|
||||
Ok(&[])
|
||||
}
|
||||
|
||||
fn data_range(&self, _address: u64, _size: u64) -> Result<Option<&'data [u8]>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn name_bytes(&self) -> Result<Option<&'data [u8]>> {
|
||||
Ok(self
|
||||
.file
|
||||
.get_name(self.file.segments[self.index].name_index))
|
||||
}
|
||||
|
||||
fn name(&self) -> Result<Option<&'data str>> {
|
||||
let index = self.file.segments[self.index].name_index;
|
||||
let name_opt = self.file.get_name(index);
|
||||
match name_opt {
|
||||
Some(bytes) => Ok(core::str::from_utf8(bytes).ok()),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn flags(&self) -> SegmentFlags {
|
||||
SegmentFlags::None
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over OMF segments.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfSegmentIterator<'data, 'file, R: ReadRef<'data>> {
|
||||
file: &'file OmfFile<'data, R>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfSegmentIterator<'data, 'file, R> {
|
||||
type Item = OmfSegmentRef<'data, 'file, R>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.file.segments.len() {
|
||||
let segment = OmfSegmentRef {
|
||||
file: self.file,
|
||||
index: self.index,
|
||||
};
|
||||
self.index += 1;
|
||||
Some(segment)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over OMF sections.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfSectionIterator<'data, 'file, R: ReadRef<'data>> {
|
||||
file: &'file OmfFile<'data, R>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfSectionIterator<'data, 'file, R> {
|
||||
type Item = OmfSection<'data, 'file, R>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.file.segments.len() {
|
||||
let section = OmfSection {
|
||||
file: self.file,
|
||||
index: self.index,
|
||||
};
|
||||
self.index += 1;
|
||||
Some(section)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A COMDAT section in an OMF file.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfComdat<'data, 'file, R: ReadRef<'data>> {
|
||||
file: &'file OmfFile<'data, R>,
|
||||
index: usize,
|
||||
_phantom: core::marker::PhantomData<&'data ()>,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for OmfComdat<'data, 'file, R> {}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for OmfComdat<'data, 'file, R> {
|
||||
type SectionIterator = OmfComdatSectionIterator<'data, 'file, R>;
|
||||
|
||||
fn kind(&self) -> ComdatKind {
|
||||
let comdat = &self.file.comdats[self.index];
|
||||
match comdat.selection {
|
||||
super::OmfComdatSelection::Explicit => ComdatKind::NoDuplicates,
|
||||
super::OmfComdatSelection::UseAny => ComdatKind::Any,
|
||||
super::OmfComdatSelection::SameSize => ComdatKind::SameSize,
|
||||
super::OmfComdatSelection::ExactMatch => ComdatKind::ExactMatch,
|
||||
}
|
||||
}
|
||||
|
||||
fn symbol(&self) -> SymbolIndex {
|
||||
// COMDAT symbols don't have a direct symbol index in OMF
|
||||
// Return an invalid index
|
||||
SymbolIndex(usize::MAX)
|
||||
}
|
||||
|
||||
fn name_bytes(&self) -> Result<&'data [u8]> {
|
||||
let comdat = &self.file.comdats[self.index];
|
||||
Ok(comdat.name)
|
||||
}
|
||||
|
||||
fn name(&self) -> Result<&'data str> {
|
||||
let comdat = &self.file.comdats[self.index];
|
||||
core::str::from_utf8(comdat.name).map_err(|_| Error("Invalid UTF-8 in COMDAT name"))
|
||||
}
|
||||
|
||||
fn sections(&self) -> Self::SectionIterator {
|
||||
let comdat = &self.file.comdats[self.index];
|
||||
OmfComdatSectionIterator {
|
||||
segment_index: if comdat.segment_index > 0 {
|
||||
Some(comdat.segment_index as usize - 1)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
returned: false,
|
||||
_phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over COMDAT sections.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfComdatIterator<'data, 'file, R: ReadRef<'data>> {
|
||||
file: &'file OmfFile<'data, R>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfComdatIterator<'data, 'file, R> {
|
||||
type Item = OmfComdat<'data, 'file, R>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.file.comdats.len() {
|
||||
let comdat = OmfComdat {
|
||||
file: self.file,
|
||||
index: self.index,
|
||||
_phantom: core::marker::PhantomData,
|
||||
};
|
||||
self.index += 1;
|
||||
Some(comdat)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over sections in a COMDAT.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfComdatSectionIterator<'data, 'file, R: ReadRef<'data>> {
|
||||
segment_index: Option<usize>,
|
||||
returned: bool,
|
||||
_phantom: core::marker::PhantomData<(&'data (), &'file (), R)>,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfComdatSectionIterator<'data, 'file, R> {
|
||||
type Item = SectionIndex;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if !self.returned {
|
||||
self.returned = true;
|
||||
self.segment_index.map(|idx| SectionIndex(idx + 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+125
-119
@@ -9,14 +9,36 @@ use crate::read::{self, Error, ReadRef, Result};
|
||||
mod file;
|
||||
pub use file::*;
|
||||
|
||||
mod relocation;
|
||||
pub use relocation::*;
|
||||
|
||||
mod section;
|
||||
pub use section::*;
|
||||
|
||||
mod segment;
|
||||
pub use segment::*;
|
||||
|
||||
mod symbol;
|
||||
pub use symbol::*;
|
||||
|
||||
mod relocation;
|
||||
pub use relocation::*;
|
||||
/// Symbol class for OMF symbols
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum OmfSymbolClass {
|
||||
/// Public symbol (PUBDEF)
|
||||
Public,
|
||||
/// Local public symbol (LPUBDEF)
|
||||
LocalPublic,
|
||||
/// External symbol (EXTDEF)
|
||||
External,
|
||||
/// Local external symbol (LEXTDEF)
|
||||
LocalExternal,
|
||||
/// Communal symbol (COMDEF)
|
||||
Communal,
|
||||
/// Local communal symbol (LCOMDEF)
|
||||
LocalCommunal,
|
||||
/// COMDAT external symbol (CEXTDEF)
|
||||
ComdatExternal,
|
||||
}
|
||||
|
||||
/// An OMF object file.
|
||||
///
|
||||
@@ -28,12 +50,10 @@ pub struct OmfFile<'data, R: ReadRef<'data> = &'data [u8]> {
|
||||
module_name: Option<&'data str>,
|
||||
/// Segment definitions
|
||||
segments: Vec<OmfSegment<'data>>,
|
||||
/// Public symbols
|
||||
publics: Vec<OmfSymbol<'data>>,
|
||||
/// External symbols
|
||||
externals: Vec<OmfSymbol<'data>>,
|
||||
/// Communal symbols from COMDEF
|
||||
communals: Vec<OmfSymbol<'data>>,
|
||||
/// All symbols (publics, externals, communals, locals) in occurrence order
|
||||
symbols: Vec<OmfSymbol<'data>>,
|
||||
/// Maps external-name table index (1-based) to SymbolIndex
|
||||
external_order: Vec<read::SymbolIndex>,
|
||||
/// COMDAT sections
|
||||
comdats: Vec<OmfComdatData<'data>>,
|
||||
/// Name table (LNAMES/LLNAMES)
|
||||
@@ -75,13 +95,15 @@ pub struct OmfSegment<'data> {
|
||||
pub relocations: Vec<OmfRelocation>,
|
||||
}
|
||||
|
||||
/// An OMF symbol (public or external)
|
||||
/// An OMF symbol
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OmfSymbol<'data> {
|
||||
/// Symbol table index
|
||||
pub symbol_index: usize,
|
||||
/// Symbol name
|
||||
pub name: &'data [u8],
|
||||
/// Symbol class (Public, External, etc.)
|
||||
pub class: OmfSymbolClass,
|
||||
/// Group index (0 if none)
|
||||
pub group_index: u16,
|
||||
/// Segment index (0 if external)
|
||||
@@ -154,19 +176,6 @@ pub enum OmfComdatSelection {
|
||||
ExactMatch = 3,
|
||||
}
|
||||
|
||||
/// A weak extern definition
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OmfWeakExtern<'data> {
|
||||
/// Weak symbol index (external symbol)
|
||||
pub weak_symbol_index: u16,
|
||||
/// Default resolution symbol index
|
||||
pub default_symbol_index: u16,
|
||||
/// Weak symbol name
|
||||
pub weak_name: &'data [u8],
|
||||
/// Default symbol name
|
||||
pub default_name: &'data [u8],
|
||||
}
|
||||
|
||||
/// Thread definition for FIXUPP parsing
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct ThreadDef {
|
||||
@@ -210,56 +219,42 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
data,
|
||||
module_name: None,
|
||||
segments: Vec::new(),
|
||||
publics: Vec::new(),
|
||||
externals: Vec::new(),
|
||||
communals: Vec::new(),
|
||||
symbols: Vec::new(),
|
||||
external_order: Vec::new(),
|
||||
comdats: Vec::new(),
|
||||
names: Vec::new(),
|
||||
groups: Vec::new(),
|
||||
};
|
||||
|
||||
file.parse_records()?;
|
||||
file.assign_symbol_indices();
|
||||
file.assign_symbol_kinds();
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
fn assign_symbol_indices(&mut self) {
|
||||
let mut index = 0;
|
||||
|
||||
// First, compute kinds for public symbols based on their segments
|
||||
let public_kinds = self
|
||||
.publics
|
||||
fn assign_symbol_kinds(&mut self) {
|
||||
// Compute kinds for symbols based on their segments
|
||||
let kinds: Vec<read::SymbolKind> = self
|
||||
.symbols
|
||||
.iter()
|
||||
.map(|sym| {
|
||||
if sym.segment_index > 0 && (sym.segment_index as usize) <= self.segments.len() {
|
||||
let segment_idx = (sym.segment_index - 1) as usize;
|
||||
let section_kind = self.segment_section_kind(segment_idx);
|
||||
Self::symbol_kind_from_section_kind(section_kind)
|
||||
} else {
|
||||
read::SymbolKind::Unknown
|
||||
.map(|sym| match sym.class {
|
||||
OmfSymbolClass::Public | OmfSymbolClass::LocalPublic => {
|
||||
if sym.segment_index > 0 && (sym.segment_index as usize) <= self.segments.len()
|
||||
{
|
||||
let segment_idx = (sym.segment_index - 1) as usize;
|
||||
let section_kind = self.segment_section_kind(segment_idx);
|
||||
Self::symbol_kind_from_section_kind(section_kind)
|
||||
} else {
|
||||
read::SymbolKind::Unknown
|
||||
}
|
||||
}
|
||||
OmfSymbolClass::Communal | OmfSymbolClass::LocalCommunal => read::SymbolKind::Data,
|
||||
_ => read::SymbolKind::Unknown,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
.collect();
|
||||
|
||||
// Assign indices to public symbols and their pre-computed kinds
|
||||
for (sym, kind) in self.publics.iter_mut().zip(public_kinds) {
|
||||
sym.symbol_index = index;
|
||||
// Apply computed kinds
|
||||
for (sym, kind) in self.symbols.iter_mut().zip(kinds) {
|
||||
sym.kind = kind;
|
||||
index += 1;
|
||||
}
|
||||
|
||||
// Assign indices to external symbols
|
||||
for sym in self.externals.iter_mut() {
|
||||
sym.symbol_index = index;
|
||||
sym.kind = read::SymbolKind::Unknown;
|
||||
index += 1;
|
||||
}
|
||||
|
||||
// Assign indices to communal symbols
|
||||
for sym in self.communals.iter_mut() {
|
||||
sym.symbol_index = index;
|
||||
sym.kind = read::SymbolKind::Data;
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +268,7 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
}
|
||||
|
||||
/// Get the section kind for a segment (reusing logic from OmfSection)
|
||||
pub fn segment_section_kind(&self, segment_index: usize) -> read::SectionKind {
|
||||
fn segment_section_kind(&self, segment_index: usize) -> read::SectionKind {
|
||||
if segment_index >= self.segments.len() {
|
||||
return read::SectionKind::Unknown;
|
||||
}
|
||||
@@ -305,8 +300,11 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
return read::SectionKind::Text;
|
||||
} else if name_upper == b"_DATA" || name_upper == b"DATA" || name_upper == b".DATA" {
|
||||
return read::SectionKind::Data;
|
||||
} else if name_upper == b"_BSS" || name_upper == b"BSS" || name_upper == b".BSS"
|
||||
|| name_upper == b"STACK" {
|
||||
} else if name_upper == b"_BSS"
|
||||
|| name_upper == b"BSS"
|
||||
|| name_upper == b".BSS"
|
||||
|| name_upper == b"STACK"
|
||||
{
|
||||
return read::SectionKind::UninitializedData;
|
||||
}
|
||||
}
|
||||
@@ -431,13 +429,33 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
self.parse_grpdef(record_data)?;
|
||||
}
|
||||
omf::record_type::PUBDEF | omf::record_type::PUBDEF32 => {
|
||||
self.parse_pubdef(record_data, record_type == omf::record_type::PUBDEF32)?;
|
||||
self.parse_pubdef(
|
||||
record_data,
|
||||
record_type == omf::record_type::PUBDEF32,
|
||||
OmfSymbolClass::Public,
|
||||
)?;
|
||||
}
|
||||
omf::record_type::LPUBDEF | omf::record_type::LPUBDEF32 => {
|
||||
self.parse_pubdef(
|
||||
record_data,
|
||||
record_type == omf::record_type::LPUBDEF32,
|
||||
OmfSymbolClass::LocalPublic,
|
||||
)?;
|
||||
}
|
||||
omf::record_type::EXTDEF => {
|
||||
self.parse_extdef(record_data)?;
|
||||
self.parse_extdef(record_data, OmfSymbolClass::External)?;
|
||||
}
|
||||
omf::record_type::LEXTDEF | omf::record_type::LEXTDEF32 => {
|
||||
self.parse_extdef(record_data, OmfSymbolClass::LocalExternal)?;
|
||||
}
|
||||
omf::record_type::CEXTDEF => {
|
||||
self.parse_extdef(record_data, OmfSymbolClass::ComdatExternal)?;
|
||||
}
|
||||
omf::record_type::COMDEF => {
|
||||
self.parse_comdef(record_data)?;
|
||||
self.parse_comdef(record_data, OmfSymbolClass::Communal)?;
|
||||
}
|
||||
omf::record_type::LCOMDEF => {
|
||||
self.parse_comdef(record_data, OmfSymbolClass::LocalCommunal)?;
|
||||
}
|
||||
omf::record_type::COMDAT | omf::record_type::COMDAT32 => {
|
||||
self.parse_comdat(record_data, record_type == omf::record_type::COMDAT32)?;
|
||||
@@ -624,7 +642,12 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_pubdef(&mut self, data: &'data [u8], is_32bit: bool) -> Result<()> {
|
||||
fn parse_pubdef(
|
||||
&mut self,
|
||||
data: &'data [u8],
|
||||
is_32bit: bool,
|
||||
class: OmfSymbolClass,
|
||||
) -> Result<()> {
|
||||
let mut offset = 0;
|
||||
|
||||
// Parse group index
|
||||
@@ -680,12 +703,13 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
|
||||
// Parse type index
|
||||
let (type_index, size) = omf::read_index(&data[offset..])
|
||||
.ok_or(Error("Invalid type index in EXTDEF record"))?;
|
||||
.ok_or(Error("Invalid type index in PUBDEF/LPUBDEF record"))?;
|
||||
offset += size;
|
||||
|
||||
self.publics.push(OmfSymbol {
|
||||
symbol_index: 0, // Will be assigned later
|
||||
self.symbols.push(OmfSymbol {
|
||||
symbol_index: self.symbols.len(),
|
||||
name,
|
||||
class,
|
||||
group_index,
|
||||
segment_index,
|
||||
frame_number,
|
||||
@@ -698,7 +722,7 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_extdef(&mut self, data: &'data [u8]) -> Result<()> {
|
||||
fn parse_extdef(&mut self, data: &'data [u8], class: OmfSymbolClass) -> Result<()> {
|
||||
let mut offset = 0;
|
||||
|
||||
while offset < data.len() {
|
||||
@@ -710,12 +734,14 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
|
||||
// Parse type index
|
||||
let (type_index, size) = omf::read_index(&data[offset..])
|
||||
.ok_or(Error("Invalid type index in EXTDEF record"))?;
|
||||
.ok_or(Error("Invalid type index in EXTDEF/LEXTDEF/CEXTDEF record"))?;
|
||||
offset += size;
|
||||
|
||||
self.externals.push(OmfSymbol {
|
||||
symbol_index: 0, // Will be assigned later
|
||||
let sym_idx = self.symbols.len();
|
||||
self.symbols.push(OmfSymbol {
|
||||
symbol_index: sym_idx,
|
||||
name,
|
||||
class,
|
||||
group_index: 0,
|
||||
segment_index: 0,
|
||||
frame_number: 0,
|
||||
@@ -723,12 +749,15 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
type_index,
|
||||
kind: read::SymbolKind::Unknown,
|
||||
});
|
||||
|
||||
// Add to external_order for symbols that contribute to external-name table
|
||||
self.external_order.push(read::SymbolIndex(sym_idx));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_comdef(&mut self, data: &'data [u8]) -> Result<()> {
|
||||
fn parse_comdef(&mut self, data: &'data [u8], class: OmfSymbolClass) -> Result<()> {
|
||||
let mut offset = 0;
|
||||
|
||||
while offset < data.len() {
|
||||
@@ -740,7 +769,7 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
|
||||
// Parse type index
|
||||
let (type_index, size) = omf::read_index(&data[offset..])
|
||||
.ok_or(Error("Invalid type index in COMDEF record"))?;
|
||||
.ok_or(Error("Invalid type index in COMDEF/LCOMDEF record"))?;
|
||||
offset += size;
|
||||
|
||||
// Parse data type and communal length
|
||||
@@ -774,9 +803,11 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
}
|
||||
};
|
||||
|
||||
self.communals.push(OmfSymbol {
|
||||
symbol_index: 0, // Will be assigned later
|
||||
let sym_idx = self.symbols.len();
|
||||
self.symbols.push(OmfSymbol {
|
||||
symbol_index: sym_idx,
|
||||
name,
|
||||
class,
|
||||
group_index: 0,
|
||||
segment_index: 0,
|
||||
frame_number: 0,
|
||||
@@ -784,6 +815,9 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
type_index,
|
||||
kind: read::SymbolKind::Data,
|
||||
});
|
||||
|
||||
// Add to external_order for symbols that contribute to external-name table
|
||||
self.external_order.push(read::SymbolIndex(sym_idx));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -1238,7 +1272,7 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
}
|
||||
|
||||
/// Expand a LIDATA block into its uncompressed form
|
||||
pub fn expand_lidata_block(&self, data: &[u8]) -> Result<Vec<u8>> {
|
||||
fn expand_lidata_block(&self, data: &[u8]) -> Result<Vec<u8>> {
|
||||
let mut offset = 0;
|
||||
let mut result = Vec::new();
|
||||
|
||||
@@ -1278,7 +1312,7 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
// Nested blocks: recurse for each block
|
||||
for _ in 0..block_count {
|
||||
let block_data = self.expand_lidata_block(&data[offset..])?;
|
||||
let block_size = self.lidata_block_size(&data[offset..])?;
|
||||
let block_size = lidata_block_size(&data[offset..])?;
|
||||
offset += block_size;
|
||||
|
||||
// Repeat the expanded block
|
||||
@@ -1291,10 +1325,6 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn lidata_block_size(&self, data: &[u8]) -> Result<usize> {
|
||||
lidata_block_size_impl(data)
|
||||
}
|
||||
|
||||
/// Get the module name
|
||||
pub fn module_name(&self) -> Option<&'data str> {
|
||||
self.module_name
|
||||
@@ -1305,46 +1335,23 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
&self.segments
|
||||
}
|
||||
|
||||
/// Get the public symbols
|
||||
pub fn publics(&self) -> &[OmfSymbol<'data>] {
|
||||
&self.publics
|
||||
}
|
||||
|
||||
/// Get the external symbols
|
||||
pub fn externals(&self) -> &[OmfSymbol<'data>] {
|
||||
&self.externals
|
||||
/// Get symbol by external-name index (1-based, as used in FIXUPP records)
|
||||
pub fn external_symbol(&self, external_index: u16) -> Option<&OmfSymbol<'data>> {
|
||||
let symbol_index = self
|
||||
.external_order
|
||||
.get(external_index.checked_sub(1)? as usize)?;
|
||||
self.symbols.get(symbol_index.0)
|
||||
}
|
||||
|
||||
/// Get a name by index (1-based)
|
||||
pub fn get_name(&self, index: u16) -> Option<&'data [u8]> {
|
||||
if index > 0 && (index as usize) <= self.names.len() {
|
||||
Some(self.names[(index - 1) as usize])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let name_index = index.checked_sub(1)?;
|
||||
self.names.get(name_index as usize).copied()
|
||||
}
|
||||
|
||||
/// Get a symbol by index
|
||||
pub fn symbol_by_index(&self, index: read::SymbolIndex) -> Result<OmfSymbol<'data>> {
|
||||
let idx = index.0;
|
||||
let total_publics = self.publics.len();
|
||||
let total_externals = self.externals.len();
|
||||
let total_before_communals = total_publics + total_externals;
|
||||
let total = total_before_communals + self.communals.len();
|
||||
|
||||
if idx >= total {
|
||||
return Err(Error("Invalid symbol index"));
|
||||
}
|
||||
|
||||
let symbol = if idx < total_publics {
|
||||
self.publics[idx].clone()
|
||||
} else if idx < total_before_communals {
|
||||
self.externals[idx - total_publics].clone()
|
||||
} else {
|
||||
self.communals[idx - total_before_communals].clone()
|
||||
};
|
||||
|
||||
Ok(symbol)
|
||||
/// Get all symbols (for iteration)
|
||||
pub fn all_symbols(&self) -> &[OmfSymbol<'data>] {
|
||||
&self.symbols
|
||||
}
|
||||
|
||||
/// Verify the checksum of an OMF record
|
||||
@@ -1375,7 +1382,7 @@ impl<'data, R: ReadRef<'data>> OmfFile<'data, R> {
|
||||
}
|
||||
|
||||
/// Helper function to calculate LIDATA block size
|
||||
fn lidata_block_size_impl(data: &[u8]) -> Result<usize> {
|
||||
fn lidata_block_size(data: &[u8]) -> Result<usize> {
|
||||
let mut offset = 0;
|
||||
|
||||
// Read repeat count
|
||||
@@ -1398,8 +1405,7 @@ fn lidata_block_size_impl(data: &[u8]) -> Result<usize> {
|
||||
} else {
|
||||
// Nested blocks
|
||||
for _ in 0..block_count {
|
||||
let nested_size = lidata_block_size_impl(&data[offset..])?;
|
||||
offset += nested_size;
|
||||
offset += lidata_block_size(&data[offset..])?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,7 @@ impl<'data, 'file, R: read::ReadRef<'data>> Iterator for OmfRelocationIterator<'
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let relocations = &self.file.segments[self.segment_index].relocations;
|
||||
if self.index >= relocations.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let reloc = &relocations[self.index];
|
||||
let reloc = relocations.get(self.index)?;
|
||||
self.index += 1;
|
||||
|
||||
// Convert OMF relocation to generic relocation
|
||||
@@ -58,13 +54,9 @@ impl<'data, 'file, R: read::ReadRef<'data>> Iterator for OmfRelocationIterator<'
|
||||
read::RelocationTarget::Section(SectionIndex(reloc.target_index as usize))
|
||||
}
|
||||
omf::TargetMethod::ExternalIndex => {
|
||||
// External indices in OMF are 1-based indices into the EXTDEF table
|
||||
// Our symbol table has publics first, then externals
|
||||
// So we need to adjust: symbol_index = publics.len() + (external_idx - 1)
|
||||
if reloc.target_index > 0 {
|
||||
let symbol_idx =
|
||||
self.file.publics.len() + (reloc.target_index as usize - 1);
|
||||
read::RelocationTarget::Symbol(read::SymbolIndex(symbol_idx))
|
||||
// External indices in OMF are 1-based indices into the external-name table
|
||||
if let Some(symbol) = self.file.external_symbol(reloc.target_index) {
|
||||
read::RelocationTarget::Symbol(read::SymbolIndex(symbol.symbol_index))
|
||||
} else {
|
||||
// Invalid external index
|
||||
read::RelocationTarget::Absolute
|
||||
|
||||
+128
-6
@@ -4,9 +4,12 @@ use alloc::borrow::Cow;
|
||||
use alloc::vec;
|
||||
use core::str;
|
||||
|
||||
use crate::read::{
|
||||
self, CompressedData, CompressedFileRange, Error, ObjectSection, ReadRef, RelocationMap,
|
||||
Result, SectionFlags, SectionIndex, SectionKind,
|
||||
use crate::{
|
||||
read::{
|
||||
self, CompressedData, CompressedFileRange, Error, ObjectSection, ReadRef, RelocationMap,
|
||||
Result, SectionFlags, SectionIndex, SectionKind,
|
||||
},
|
||||
ComdatKind, ObjectComdat, SymbolIndex,
|
||||
};
|
||||
|
||||
use super::{relocation::OmfRelocationIterator, OmfDataChunk, OmfFile, OmfSegment};
|
||||
@@ -71,8 +74,9 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for OmfSection<'data,
|
||||
}
|
||||
|
||||
// For multiple chunks, LIDATA, or non-contiguous data, we can't return a reference
|
||||
// Users should use uncompressed_data() instead for these cases
|
||||
Err(Error("OMF segment data is not contiguous; use uncompressed_data() instead"))
|
||||
Err(Error(
|
||||
"OMF segment data is not contiguous; use uncompressed_data() instead",
|
||||
))
|
||||
}
|
||||
|
||||
fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
|
||||
@@ -139,7 +143,7 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for OmfSection<'data,
|
||||
|
||||
match chunk {
|
||||
OmfDataChunk::Direct(data) => {
|
||||
// Direct data - just copy it
|
||||
// Direct data
|
||||
let end = start + data.len();
|
||||
if end <= result.len() {
|
||||
result[start..end].copy_from_slice(data);
|
||||
@@ -217,3 +221,121 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for OmfSection<'data,
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over OMF sections.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfSectionIterator<'data, 'file, R: ReadRef<'data>> {
|
||||
pub(super) file: &'file OmfFile<'data, R>,
|
||||
pub(super) index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfSectionIterator<'data, 'file, R> {
|
||||
type Item = OmfSection<'data, 'file, R>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.file.segments.len() {
|
||||
let section = OmfSection {
|
||||
file: self.file,
|
||||
index: self.index,
|
||||
};
|
||||
self.index += 1;
|
||||
Some(section)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A COMDAT section in an OMF file.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfComdat<'data, 'file, R: ReadRef<'data>> {
|
||||
file: &'file OmfFile<'data, R>,
|
||||
index: usize,
|
||||
_phantom: core::marker::PhantomData<&'data ()>,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for OmfComdat<'data, 'file, R> {}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for OmfComdat<'data, 'file, R> {
|
||||
type SectionIterator = OmfComdatSectionIterator<'data, 'file, R>;
|
||||
|
||||
fn kind(&self) -> ComdatKind {
|
||||
let comdat = &self.file.comdats[self.index];
|
||||
match comdat.selection {
|
||||
super::OmfComdatSelection::Explicit => ComdatKind::NoDuplicates,
|
||||
super::OmfComdatSelection::UseAny => ComdatKind::Any,
|
||||
super::OmfComdatSelection::SameSize => ComdatKind::SameSize,
|
||||
super::OmfComdatSelection::ExactMatch => ComdatKind::ExactMatch,
|
||||
}
|
||||
}
|
||||
|
||||
fn symbol(&self) -> SymbolIndex {
|
||||
// COMDAT symbols don't have a direct symbol index in OMF
|
||||
SymbolIndex(usize::MAX)
|
||||
}
|
||||
|
||||
fn name_bytes(&self) -> Result<&'data [u8]> {
|
||||
let comdat = &self.file.comdats[self.index];
|
||||
Ok(comdat.name)
|
||||
}
|
||||
|
||||
fn name(&self) -> Result<&'data str> {
|
||||
let comdat = &self.file.comdats[self.index];
|
||||
core::str::from_utf8(comdat.name).map_err(|_| Error("Invalid UTF-8 in COMDAT name"))
|
||||
}
|
||||
|
||||
fn sections(&self) -> Self::SectionIterator {
|
||||
let comdat = &self.file.comdats[self.index];
|
||||
OmfComdatSectionIterator {
|
||||
segment_index: (comdat.segment_index as usize).checked_sub(1),
|
||||
returned: false,
|
||||
_phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over COMDAT sections.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfComdatIterator<'data, 'file, R: ReadRef<'data>> {
|
||||
pub(super) file: &'file OmfFile<'data, R>,
|
||||
pub(super) index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfComdatIterator<'data, 'file, R> {
|
||||
type Item = OmfComdat<'data, 'file, R>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.file.comdats.len() {
|
||||
let comdat = OmfComdat {
|
||||
file: self.file,
|
||||
index: self.index,
|
||||
_phantom: core::marker::PhantomData,
|
||||
};
|
||||
self.index += 1;
|
||||
Some(comdat)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over sections in a COMDAT.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfComdatSectionIterator<'data, 'file, R: ReadRef<'data>> {
|
||||
segment_index: Option<usize>,
|
||||
returned: bool,
|
||||
_phantom: core::marker::PhantomData<(&'data (), &'file (), R)>,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfComdatSectionIterator<'data, 'file, R> {
|
||||
type Item = SectionIndex;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if !self.returned {
|
||||
self.returned = true;
|
||||
self.segment_index.map(|idx| SectionIndex(idx + 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
use crate::{read, ObjectSegment, ReadRef, Result, SegmentFlags};
|
||||
|
||||
use super::OmfFile;
|
||||
|
||||
/// An OMF segment reference.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfSegmentRef<'data, 'file, R: ReadRef<'data>> {
|
||||
file: &'file OmfFile<'data, R>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for OmfSegmentRef<'data, 'file, R> {}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for OmfSegmentRef<'data, 'file, R> {
|
||||
fn address(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
fn size(&self) -> u64 {
|
||||
self.file.segments[self.index].length as u64
|
||||
}
|
||||
|
||||
fn align(&self) -> u64 {
|
||||
match self.file.segments[self.index].alignment {
|
||||
crate::omf::SegmentAlignment::Byte => 1,
|
||||
crate::omf::SegmentAlignment::Word => 2,
|
||||
crate::omf::SegmentAlignment::Paragraph => 16,
|
||||
crate::omf::SegmentAlignment::Page => 256,
|
||||
crate::omf::SegmentAlignment::DWord => 4,
|
||||
crate::omf::SegmentAlignment::Page4K => 4096,
|
||||
_ => 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn file_range(&self) -> (u64, u64) {
|
||||
(0, 0)
|
||||
}
|
||||
|
||||
fn data(&self) -> Result<&'data [u8]> {
|
||||
// OMF segments don't have direct file mapping
|
||||
Ok(&[])
|
||||
}
|
||||
|
||||
fn data_range(&self, _address: u64, _size: u64) -> Result<Option<&'data [u8]>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn name_bytes(&self) -> Result<Option<&'data [u8]>> {
|
||||
Ok(self
|
||||
.file
|
||||
.get_name(self.file.segments[self.index].name_index))
|
||||
}
|
||||
|
||||
fn name(&self) -> Result<Option<&'data str>> {
|
||||
let index = self.file.segments[self.index].name_index;
|
||||
let name_opt = self.file.get_name(index);
|
||||
match name_opt {
|
||||
Some(bytes) => Ok(core::str::from_utf8(bytes).ok()),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn flags(&self) -> SegmentFlags {
|
||||
SegmentFlags::None
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over OMF segments.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfSegmentIterator<'data, 'file, R: ReadRef<'data>> {
|
||||
pub(super) file: &'file OmfFile<'data, R>,
|
||||
pub(super) index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfSegmentIterator<'data, 'file, R> {
|
||||
type Item = OmfSegmentRef<'data, 'file, R>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.file.segments.len() {
|
||||
let segment = OmfSegmentRef {
|
||||
file: self.file,
|
||||
index: self.index,
|
||||
};
|
||||
self.index += 1;
|
||||
Some(segment)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
-37
@@ -64,10 +64,10 @@ impl<'data> ObjectSymbol<'data> for OmfSymbol<'data> {
|
||||
}
|
||||
|
||||
fn is_common(&self) -> bool {
|
||||
// Communal symbols have segment_index == 0, frame_number == 0, but offset != 0
|
||||
// The offset field stores the size of the communal symbol
|
||||
// This excludes both externals (offset == 0) and absolute symbols (frame_number != 0)
|
||||
self.segment_index == 0 && self.frame_number == 0 && self.offset != 0
|
||||
matches!(
|
||||
self.class,
|
||||
super::OmfSymbolClass::Communal | super::OmfSymbolClass::LocalCommunal
|
||||
)
|
||||
}
|
||||
|
||||
fn is_weak(&self) -> bool {
|
||||
@@ -75,19 +75,34 @@ impl<'data> ObjectSymbol<'data> for OmfSymbol<'data> {
|
||||
}
|
||||
|
||||
fn scope(&self) -> SymbolScope {
|
||||
if self.segment_index == 0 {
|
||||
SymbolScope::Unknown
|
||||
} else {
|
||||
SymbolScope::Linkage
|
||||
match self.class {
|
||||
super::OmfSymbolClass::LocalPublic
|
||||
| super::OmfSymbolClass::LocalExternal
|
||||
| super::OmfSymbolClass::LocalCommunal => SymbolScope::Compilation,
|
||||
super::OmfSymbolClass::Public
|
||||
| super::OmfSymbolClass::External
|
||||
| super::OmfSymbolClass::Communal
|
||||
| super::OmfSymbolClass::ComdatExternal => {
|
||||
if self.segment_index == 0 {
|
||||
SymbolScope::Unknown
|
||||
} else {
|
||||
SymbolScope::Linkage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_global(&self) -> bool {
|
||||
true
|
||||
!self.is_local()
|
||||
}
|
||||
|
||||
fn is_local(&self) -> bool {
|
||||
false
|
||||
matches!(
|
||||
self.class,
|
||||
super::OmfSymbolClass::LocalPublic
|
||||
| super::OmfSymbolClass::LocalExternal
|
||||
| super::OmfSymbolClass::LocalCommunal
|
||||
)
|
||||
}
|
||||
|
||||
fn flags(&self) -> SymbolFlags<SectionIndex, SymbolIndex> {
|
||||
@@ -97,34 +112,16 @@ impl<'data> ObjectSymbol<'data> for OmfSymbol<'data> {
|
||||
|
||||
/// An iterator over OMF symbols.
|
||||
#[derive(Debug)]
|
||||
pub struct OmfSymbolIterator<'data, 'file> {
|
||||
pub(super) publics: &'file [OmfSymbol<'data>],
|
||||
pub(super) externals: &'file [OmfSymbol<'data>],
|
||||
pub(super) communals: &'file [OmfSymbol<'data>],
|
||||
pub struct OmfSymbolIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> {
|
||||
pub(super) file: &'file OmfFile<'data, R>,
|
||||
pub(super) index: usize,
|
||||
}
|
||||
|
||||
impl<'data, 'file> Iterator for OmfSymbolIterator<'data, 'file> {
|
||||
impl<'data, 'file, R: ReadRef<'data>> Iterator for OmfSymbolIterator<'data, 'file, R> {
|
||||
type Item = OmfSymbol<'data>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let total_publics = self.publics.len();
|
||||
let total_externals = self.externals.len();
|
||||
let total_before_communals = total_publics + total_externals;
|
||||
let total = total_before_communals + self.communals.len();
|
||||
|
||||
if self.index >= total {
|
||||
return None;
|
||||
}
|
||||
|
||||
let symbol = if self.index < total_publics {
|
||||
self.publics[self.index].clone()
|
||||
} else if self.index < total_before_communals {
|
||||
self.externals[self.index - total_publics].clone()
|
||||
} else {
|
||||
self.communals[self.index - total_before_communals].clone()
|
||||
};
|
||||
|
||||
let symbol = self.file.symbols.get(self.index)?.clone();
|
||||
self.index += 1;
|
||||
Some(symbol)
|
||||
}
|
||||
@@ -140,18 +137,20 @@ impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for OmfSymbolTable<'
|
||||
|
||||
impl<'data, 'file, R: ReadRef<'data>> ObjectSymbolTable<'data> for OmfSymbolTable<'data, 'file, R> {
|
||||
type Symbol = OmfSymbol<'data>;
|
||||
type SymbolIterator = OmfSymbolIterator<'data, 'file>;
|
||||
type SymbolIterator = OmfSymbolIterator<'data, 'file, R>;
|
||||
|
||||
fn symbols(&self) -> Self::SymbolIterator {
|
||||
OmfSymbolIterator {
|
||||
publics: &self.file.publics,
|
||||
externals: &self.file.externals,
|
||||
communals: &self.file.communals,
|
||||
file: self.file,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> {
|
||||
self.file.symbol_by_index(index)
|
||||
self.file
|
||||
.symbols
|
||||
.get(index.0)
|
||||
.cloned()
|
||||
.ok_or(Error("Symbol index out of bounds"))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user