Skip to main content

A Python library for direct, low-level memory management.

Project description

locmem - Low-Level Memory Management for Python

PyPI version Build Status License: MIT

locmem is a Python library that provides a powerful toolkit for direct, low-level memory management. It allows you to bypass Python's standard memory allocation and interact with memory at a level similar to C.

Key Features

  • Direct Memory Control: Allocate and free raw memory blocks on demand.
  • Smart Pointer Class: A robust wrapper around memory addresses with support for arithmetic, context management (with statement), and automatic garbage collection.
  • C-Style Memory Operations: A suite of familiar functions including memread, memwrite, memcpy, and memset.
  • High-Level Data Types: Work with Int, Float and other C-like types that live directly in the memory you manage.
  • Executable Memory: Allocate memory with execute permissions and run machine code directly using memexec.
  • Cross-Platform: Works seamlessly on Windows and POSIX-compliant systems (Linux, macOS).

Installation

pip install locmem

Quick Start

The easiest way to use locmem is with the with statement, which ensures that memory is automatically freed when you're done.

from locmem import alloc, memwrite, Int

# The `with` block ensures the pointer `p` is automatically freed upon exit.
with alloc(16) as p:
    print(f"Allocated 16 bytes at address: {p}")

    # Write a 32-bit integer (value 12345) to the start of the memory block
    value_to_write = 12345
    memwrite(p, value_to_write.to_bytes(4, 'little'))
    print(f"Wrote the value {value_to_write} to memory.")

    # Create a locmem.Int object that is mapped to that memory location.
    # It reads and interprets the bytes at that address.
    my_int = Int.from_ptr(p)

    print(f"Value read via Int object: {my_int.value}")
    assert my_int.value == value_to_write

    # You can also modify the underlying memory through the object.
    my_int.value = 54321
    print(f"Changed value to: {my_int.value}")

    # The memory is automatically freed here.
print("Memory has been freed.")

Core Concepts

1. Allocation & Pointers

The library revolves around the Pointer object, which is returned by the alloc function.

from locmem import alloc, free

# Manual allocation
ptr = alloc(32)

# Pointers support arithmetic
ptr2 = ptr + 16
print(f"Original: {ptr}, Offset: {ptr2}")

# Manually free the memory when done
free(ptr)
# Or, even better, call the method on the pointer itself
# ptr.free()

The Pointer object's __del__ method will automatically call free, but relying on Python's garbage collector for timely memory release is not recommended. Always use the with statement or call free() explicitly.

2. High-Level Data Types

locmem provides classes that mirror C data types. These objects manage their own memory and handle the packing/unpacking of data for you. They also support standard arithmetic and comparison operations.

from locmem import Int, Double, Char

# These objects allocate their own memory upon creation.
a = Int(100)
b = Int(50)

c = a + b  # c is a new Int object with value 150
c -= 20    # c.value is now 130

print(f"Result: {c.value}")

# Perform float arithmetic
d = Double(1.25)
e = Double(4.0)
f = d * e  # f is a new Double object with value 5.0
print(f"Float result: {f.value}")

# These objects will free their memory when they go out of scope.

3. Executable Memory

A powerful feature of locmem is the ability to allocate executable memory. This allows you to write machine code into memory and then call it like a regular Python function.

from locmem import alloc, memwrite, memexec
import ctypes

# x86-64 machine code for a function that returns 42:
# mov eax, 42   ; b8 2a 00 00 00
# ret           ; c3
shellcode = b'\xb8\x2a\x00\x00\x00\xc3'

# Allocate memory with executable permissions
with alloc(len(shellcode), executable=True) as p:
    # Write the machine code to the allocated block
    memwrite(p, shellcode)
  
    # Create a callable Python function from the memory address.
    # Specify that it takes no arguments and returns a C integer.
    func = memexec(p, restype=ctypes.c_int)

    # Call the function!
    result = func()
    print(f"Executed code from memory, result: {result}")
    assert result == 42

Advanced Usage

Choosing an Allocator

locmem ships with two main allocator types. The BinnedAllocator is the default because it's highly efficient for programs that make many small allocations. However, you can switch to the simpler HeapAllocator if you prefer.

The global allocator can be changed at runtime.

from locmem import alloc, set_global_allocator, HeapAllocator, BinnedAllocator

# The default is BinnedAllocator
ptr1 = alloc(16)
print(f"Allocated with: {type(ptr1._deref.__self__)}")
# > Allocated with: <class 'locmem.allocator.binned.BinnedAllocator'>
ptr1.free()


# Switch to the HeapAllocator for all subsequent allocations
set_global_allocator(HeapAllocator())

ptr2 = alloc(16)
print(f"Allocated with: {type(ptr2._deref.__self__)}")
# > Allocated with: <class 'locmem.allocator.heap.HeapAllocator'>
ptr2.free()

Project Architecture

locmem is built on a layered architecture:

  1. OS Memory Layer (locmem.os_mem): The lowest level. It contains platform-specific code (mmap for POSIX, VirtualAlloc for Windows) to request memory directly from the operating system.
  2. Allocator Layer (locmem.allocator): This layer sits on top of the OS layer. It implements allocation strategies (BinnedAllocator, HeapAllocator) to manage the raw memory obtained from the OS efficiently.
  3. Core API (locmem.core, locmem.datatype): The highest level. It provides the user-facing Pointer object, memory manipulation functions (memread, memwrite, etc.), and the high-level Int, Float data types.

Contributing

Contributions are welcome! If you find a bug, have a feature request, or want to improve the documentation, please open an issue or submit a pull request on our GitHub repository.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

locmem-0.1.0.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

locmem-0.1.0-py3-none-any.whl (16.1 kB view details)

Uploaded Python 3

File details

Details for the file locmem-0.1.0.tar.gz.

File metadata

  • Download URL: locmem-0.1.0.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for locmem-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c6e65b3fb342d9070d166e3799a6a60037ae39abec71ebb2d435d3d3eedcb2e0
MD5 d2f534d27713d2e1c2fcb5dc765e8f23
BLAKE2b-256 2fa115397a57e3fc396cf66915e306574506edd38a7ee163e2c558eb5bf94ca0

See more details on using hashes here.

File details

Details for the file locmem-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: locmem-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for locmem-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ffae2442fba4b8876f50bbc7e41dd5ce97810fdd5384d5e41728dbb104fdad44
MD5 fe87bde380b87f33be6e7be4b270d342
BLAKE2b-256 61a09d9c53d38a292298640c9529fee32d80365c0916feb00451cc30e9cb96aa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page