Skip to content

Commit 68f4552

Browse files
committed
Better support for SMG/TP maps
These maps are post-processed and have various issues. This includes some hacks to work around those issues as much as possible.
1 parent ac45676 commit 68f4552

File tree

1 file changed

+107
-8
lines changed

1 file changed

+107
-8
lines changed

src/util/map.rs

+107-8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::{
1111
use anyhow::{anyhow, bail, Error, Result};
1212
use cwdemangle::{demangle, DemangleOptions};
1313
use flagset::FlagSet;
14+
use indexmap::IndexMap;
1415
use itertools::Itertools;
1516
use multimap::MultiMap;
1617
use once_cell::sync::Lazy;
@@ -128,7 +129,7 @@ pub struct MapInfo {
128129
pub unit_references: MultiMap<SymbolRef, String>,
129130
pub sections: Vec<SectionInfo>,
130131
pub link_map_symbols: HashMap<SymbolRef, SymbolEntry>,
131-
pub section_symbols: HashMap<String, BTreeMap<u32, Vec<SymbolEntry>>>,
132+
pub section_symbols: IndexMap<String, BTreeMap<u32, Vec<SymbolEntry>>>,
132133
pub section_units: HashMap<String, Vec<(u32, String)>>,
133134
// For common BSS inflation correction
134135
pub common_bss_start: Option<u32>,
@@ -723,13 +724,51 @@ where
723724
{
724725
let file = map_file(&path)?;
725726
let info = process_map(&mut file.as_reader(), common_bss_start, mw_comment_version)?;
726-
apply_map(&info, obj)
727+
apply_map(info, obj)
727728
}
728729

729-
pub fn apply_map(result: &MapInfo, obj: &mut ObjInfo) -> Result<()> {
730+
const DEFAULT_REL_SECTIONS: &[&str] =
731+
&[".init", ".text", ".ctors", ".dtors", ".rodata", ".data", ".bss"];
732+
733+
fn normalize_section_name(name: &str) -> &str {
734+
match name {
735+
".extabindex" => "extabindex",
736+
".extab" => "extab",
737+
_ => name,
738+
}
739+
}
740+
741+
pub fn apply_map(mut result: MapInfo, obj: &mut ObjInfo) -> Result<()> {
742+
if result.sections.is_empty() && obj.kind == ObjKind::Executable {
743+
log::warn!("Memory map section missing, attempting to recreate");
744+
for (section_name, symbol_map) in &result.section_symbols {
745+
let mut address = u32::MAX;
746+
let mut size = 0;
747+
for symbol_entry in symbol_map.values().flatten() {
748+
if symbol_entry.address < address {
749+
address = symbol_entry.address;
750+
}
751+
if symbol_entry.address + symbol_entry.size > address + size {
752+
size = symbol_entry.address + symbol_entry.size - address;
753+
}
754+
}
755+
log::info!("Recreated section {} @ {:#010X} ({:#X})", section_name, address, size);
756+
result.sections.push(SectionInfo {
757+
name: normalize_section_name(section_name).to_string(),
758+
address,
759+
size,
760+
file_offset: 0,
761+
});
762+
}
763+
}
764+
730765
for (section_index, section) in obj.sections.iter_mut() {
731766
let opt = if obj.kind == ObjKind::Executable {
732-
result.sections.iter().find(|s| s.address == section.address as u32)
767+
result.sections.iter().find(|s| {
768+
// Slightly fuzzy match for postprocess/broken maps (TP, SMG)
769+
s.address >= section.address as u32
770+
&& (s.address + s.size) <= (section.address + section.size) as u32
771+
})
733772
} else {
734773
result.sections.iter().filter(|s| s.size > 0).nth(section_index)
735774
};
@@ -754,17 +793,61 @@ pub fn apply_map(result: &MapInfo, obj: &mut ObjInfo) -> Result<()> {
754793
section.rename(info.name.clone())?;
755794
} else {
756795
log::warn!("Section {} @ {:#010X} not found in map", section.name, section.address);
796+
if obj.kind == ObjKind::Relocatable {
797+
let new_name = match section.kind {
798+
ObjSectionKind::Code => {
799+
if section.elf_index == 0 {
800+
".init"
801+
} else {
802+
".text"
803+
}
804+
}
805+
ObjSectionKind::Data | ObjSectionKind::ReadOnlyData => {
806+
if section.elf_index == 4 {
807+
if result
808+
.section_symbols
809+
.get(".rodata")
810+
.map_or(false, |m| !m.is_empty())
811+
{
812+
".rodata"
813+
} else {
814+
".data"
815+
}
816+
} else if let Some(section_name) =
817+
DEFAULT_REL_SECTIONS.get(section.elf_index)
818+
{
819+
section_name
820+
} else {
821+
".data"
822+
}
823+
}
824+
ObjSectionKind::Bss => ".bss",
825+
};
826+
log::warn!("Defaulting to {}", new_name);
827+
section.rename(new_name.to_string())?;
828+
}
757829
}
758830
}
759831

832+
// If every symbol the map has alignment 4, it's likely bogus
833+
let bogus_alignment =
834+
result.section_symbols.values().flatten().flat_map(|(_, m)| m).all(|s| s.align == Some(4));
835+
if bogus_alignment {
836+
log::warn!("Bogus alignment detected, ignoring");
837+
}
838+
760839
// Add section symbols
761840
for (section_name, symbol_map) in &result.section_symbols {
841+
if section_name == ".dead" {
842+
continue;
843+
}
844+
let section_name = normalize_section_name(section_name);
762845
let (section_index, _) = obj
763846
.sections
764847
.by_name(section_name)?
765848
.ok_or_else(|| anyhow!("Failed to locate section {section_name} from map"))?;
766849
for symbol_entry in symbol_map.values().flatten() {
767-
add_symbol(obj, symbol_entry, Some(section_index))?;
850+
add_symbol(obj, symbol_entry, Some(section_index), bogus_alignment)?;
768851
}
769852
}
770853

@@ -776,6 +859,10 @@ pub fn apply_map(result: &MapInfo, obj: &mut ObjInfo) -> Result<()> {
776859

777860
// Add splits
778861
for (section_name, unit_order) in &result.section_units {
862+
if section_name == ".dead" {
863+
continue;
864+
}
865+
let section_name = normalize_section_name(section_name);
779866
let (_, section) = obj
780867
.sections
781868
.iter_mut()
@@ -865,14 +952,21 @@ pub fn create_obj(result: &MapInfo) -> Result<ObjInfo> {
865952
unresolved_relocations: vec![],
866953
};
867954

955+
// If every symbol the map has alignment 4, it's likely bogus
956+
let bogus_alignment =
957+
result.section_symbols.values().flatten().flat_map(|(_, m)| m).all(|s| s.align == Some(4));
958+
if bogus_alignment {
959+
log::warn!("Bogus alignment detected, ignoring");
960+
}
961+
868962
// Add section symbols
869963
for (section_name, symbol_map) in &result.section_symbols {
870964
let (section_index, _) = obj
871965
.sections
872966
.by_name(section_name)?
873967
.ok_or_else(|| anyhow!("Failed to locate section {section_name} from map"))?;
874968
for symbol_entry in symbol_map.values().flatten() {
875-
add_symbol(&mut obj, symbol_entry, Some(section_index))?;
969+
add_symbol(&mut obj, symbol_entry, Some(section_index), bogus_alignment)?;
876970
}
877971
}
878972

@@ -917,7 +1011,12 @@ pub fn create_obj(result: &MapInfo) -> Result<ObjInfo> {
9171011
Ok(obj)
9181012
}
9191013

920-
fn add_symbol(obj: &mut ObjInfo, symbol_entry: &SymbolEntry, section: Option<usize>) -> Result<()> {
1014+
fn add_symbol(
1015+
obj: &mut ObjInfo,
1016+
symbol_entry: &SymbolEntry,
1017+
section: Option<usize>,
1018+
ignore_alignment: bool,
1019+
) -> Result<()> {
9211020
let demangled_name = demangle(&symbol_entry.name, &DemangleOptions::default());
9221021
let mut flags: FlagSet<ObjSymbolFlags> = match symbol_entry.visibility {
9231022
SymbolVisibility::Unknown => Default::default(),
@@ -947,7 +1046,7 @@ fn add_symbol(obj: &mut ObjInfo, symbol_entry: &SymbolEntry, section: Option<usi
9471046
SymbolKind::Section => ObjSymbolKind::Section,
9481047
SymbolKind::NoType => ObjSymbolKind::Unknown,
9491048
},
950-
align: symbol_entry.align,
1049+
align: if ignore_alignment { None } else { symbol_entry.align },
9511050
..Default::default()
9521051
},
9531052
true,

0 commit comments

Comments
 (0)