ld-so-cache 0.1.0

A parser for glibc ld.so.cache files
Documentation
# ld-so-cache

A comprehensive Rust parser for Linux `ld.so.cache` files with 100% compatibility with `ldconfig` output.

## Overview

The `ld.so.cache` file is used by the Linux dynamic linker to quickly locate shared libraries. This crate provides a complete parser that can read both legacy (ld.so-1.7.0) and modern (glibc) cache formats, extracting library names, paths, and hardware capability information.

## Features

- **Complete Format Support**: Handles both old (ld.so-1.7.0) and new (glibc) cache formats
- **Hardware Capabilities**: Parses hardware capability flags including ISA levels and processor features
- **Extension Support**: Handles cache extensions for future format enhancements
- **Error Resilience**: Gracefully handles corrupted or truncated cache files
- **100% ldconfig Compatibility**: Produces identical output to `ldconfig -p` across many major distributions
- **Cross-Platform**: Works on any platform that can read the cache files

## Verified Compatibility

This parser has been tested against real cache files from:

- **Debian**: Bookworm, Trixie
- **Ubuntu**: Jammy (22.04), Noble (24.04), Questing (25.04)
- **AlmaLinux**: 8, 9, 10
- **Red Hat**: UBI 8

All tests show **exact matches** with `ldconfig -p` output.

## Quick Start

### Library Usage

```rust
use ld_so_cache::parsers::parse_ld_cache;
use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Parse the system's ld.so.cache file
    let data = fs::read("/etc/ld.so.cache")?;
    let cache = parse_ld_cache(&data)?;

    // Extract all library entries
    let entries = cache.get_entries()?;
    for entry in entries {
        println!("{} -> {}", entry.library_name, entry.library_path);
        
        // Check if it's an ELF library
        if entry.flags & 1 != 0 {
            println!("  ELF library");
        }
        
        // Display hardware capabilities if present
        if let Some(hwcap) = entry.hwcap {
            let isa_level = (hwcap >> 52) & 0x3ff;
            if isa_level > 0 {
                println!("  Requires ISA level: {}", isa_level);
            }
        }
    }
    
    Ok(())
}
```

### Command Line Usage

The crate includes a CLI tool for inspecting cache files:

```bash
# Parse the system cache
ld-cache-parser

# Parse a specific cache file
ld-cache-parser -f /path/to/ld.so.cache

# Show detailed information including hardware capabilities
ld-cache-parser --verbose

# Output in JSON format
ld-cache-parser --format json

# Show only cache statistics
ld-cache-parser --stats
```

## Cache Formats

### Legacy Format (ld.so-1.7.0)

The old format provides basic library name to path mappings:

```rust
use ld_so_cache::OldFileEntry;

let entry = OldFileEntry {
    flags: 1,      // ELF library
    key: 0,        // Offset to library name
    value: 10,     // Offset to library path
};
```

### Modern Format (glibc)

The new format includes hardware capabilities and extensions:

```rust
use ld_so_cache::NewFileEntry;

let entry = NewFileEntry {
    flags: 1,
    key: 0,
    value: 10,
    osversion_unused: 0,
    hwcap: 0x0020_0000_0000_1234, // Hardware capabilities
};

// Extract ISA level (bits 52-61)
let isa_level = (entry.hwcap >> 52) & 0x3ff;

// Check for extension flag (bit 62)
let has_extensions = entry.hwcap & (1u64 << 62) != 0;

// Get CPU features (bits 0-51)
let cpu_features = entry.hwcap & ((1u64 << 52) - 1);
```

## Hardware Capabilities

The parser correctly decodes hardware capability information:

- **ISA Levels**: x86-64-v2, x86-64-v3, etc. (bits 52-61)
- **Extension Flag**: Indicates additional capability data (bit 62)
- **CPU Features**: Various processor features like SSE, AVX (bits 0-51)
- **Architecture**: i386, x86-64, libx32 from flags field

## Error Handling

The library provides comprehensive error handling:

```rust
use ld_so_cache::{CacheError, parsers::parse_ld_cache};

match parse_ld_cache(&data) {
    Ok(cache) => {
        // Process cache entries
        match cache.get_entries() {
            Ok(entries) => println!("Found {} libraries", entries.len()),
            Err(CacheError::InvalidStringOffset(offset)) => {
                eprintln!("Corrupted string table at offset {}", offset);
            }
            Err(e) => eprintln!("Error extracting entries: {}", e),
        }
    }
    Err(CacheError::InvalidMagic) => {
        eprintln!("Not a valid ld.so.cache file");
    }
    Err(CacheError::TruncatedFile) => {
        eprintln!("Cache file is incomplete");
    }
    Err(e) => eprintln!("Parse error: {}", e),
}
```

## JSON Output

The library supports JSON serialization with proper formatting:

```json
{
  "library_name": "libc.so.6",
  "library_path": "/lib/x86_64-linux-gnu/libc.so.6",
  "flags": 769,
  "hwcap": "0x0000000000001000"
}
```

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
ld-so-cache = "0.1"
```

Or install the CLI tool:

```bash
cargo install ld-so-cache
```

## Documentation

Full API documentation is available at [docs.rs](https://docs.rs/ld-so-cache).

The library includes extensive documentation with examples for all public APIs.

## Testing

The crate includes comprehensive tests:

- **Unit Tests**: All core parsing functionality
- **Integration Tests**: Real cache files from multiple distributions  
- **Compatibility Tests**: Verification against `ldconfig -p` output
- **Documentation Tests**: All code examples are tested

Run tests with:

```bash
cargo test
```

## License

This project is licensed under the CC0 License - see the `LICENSE.md` file for details.

## AI Disclaimer

This library was built with the help of Claude Code. This README was significantly written by Claude. I wanted to get this quickly built, so I took a shortcut.