Analyze ALL symbols in ELF file using both nm and readelf for comprehensive coverage
(
elf_file: str, nm_path: str, cppfilt_path: str, readelf_path: Optional[str] = None
)
| 175 | |
| 176 | |
| 177 | def analyze_symbols( |
| 178 | elf_file: str, nm_path: str, cppfilt_path: str, readelf_path: Optional[str] = None |
| 179 | ) -> list[SymbolInfo]: |
| 180 | """Analyze ALL symbols in ELF file using both nm and readelf for comprehensive coverage""" |
| 181 | print("Analyzing symbols with enhanced coverage...") |
| 182 | |
| 183 | symbols: list[SymbolInfo] = [] |
| 184 | symbols_dict: dict[ |
| 185 | str, SymbolInfo |
| 186 | ] = {} # To deduplicate by address+type (or demangled name for zero-address symbols) |
| 187 | |
| 188 | # Method 1: Use readelf to get ALL symbols (including those without size) |
| 189 | if readelf_path: |
| 190 | print("Getting all symbols using readelf...") |
| 191 | readelf_cmd = f'"{readelf_path}" -s "{elf_file}"' |
| 192 | output = run_command(readelf_cmd) |
| 193 | |
| 194 | if output: |
| 195 | for line in output.strip().split("\n"): |
| 196 | line = line.strip() |
| 197 | # Skip header and empty lines |
| 198 | if ( |
| 199 | not line |
| 200 | or "Num:" in line |
| 201 | or "Symbol table" in line |
| 202 | or line.startswith("--") |
| 203 | ): |
| 204 | continue |
| 205 | |
| 206 | # Parse readelf output format: Num: Value Size Type Bind Vis Ndx Name |
| 207 | parts = line.split() |
| 208 | if len(parts) >= 8: |
| 209 | try: |
| 210 | # Skip num (parts[0]) - not needed |
| 211 | addr = parts[1] |
| 212 | size = int(parts[2]) if parts[2].isdigit() else 0 |
| 213 | symbol_type = parts[3] |
| 214 | parts[4] |
| 215 | # Skip vis and ndx (parts[5], parts[6]) - not needed |
| 216 | name = " ".join(parts[7:]) if len(parts) > 7 else "" |
| 217 | |
| 218 | # Skip empty names and section symbols |
| 219 | if not name or name.startswith(".") or symbol_type == "SECTION": |
| 220 | continue |
| 221 | |
| 222 | # Demangle the symbol name |
| 223 | demangled_name = demangle_symbol(name, cppfilt_path) |
| 224 | |
| 225 | # Normalize address to int for comparison (readelf uses hex) |
| 226 | try: |
| 227 | addr_int = int(addr, 16) |
| 228 | except ValueError: |
| 229 | addr_int = 0 |
| 230 | |
| 231 | # Create key: Use address ONLY for non-zero addresses (symbol type can vary between tools) |
| 232 | # For zero-address symbols, use demangled_name+type to catch duplicates |
| 233 | sym_type_char = symbol_type[0].upper() |
| 234 | if addr_int != 0: |