structstd.debug.Info[src]

Cross-platform abstraction for loading debug information into an in-memory format that supports queries such as "what is the source location of this virtual memory address?"

Unlike std.debug.SelfInfo, this API does not assume the debug information in question happens to match the host CPU architecture, OS, or other target properties.

Fields

address_map: std.AutoArrayHashMapUnmanaged(u64, Dwarf.ElfModule)

Sorted by key, ascending.

coverage: *Coverage

Externally managed, outlives this Info instance.

Error Sets

Error SetLoadError[src]

Errors

anyerror means the error set is known only at runtime.

AccessDenied OpenError

In WASI, this error may occur when the file descriptor does not hold the required rights to open a new resource relative to it.

AntivirusInterference OpenError

On Windows, antivirus software is enabled by default. It can be disabled, but Windows Update sometimes ignores the user's preference and re-enables it. When enabled, antivirus software on Windows intercepts file system operations and makes them significantly slower in addition to possibly failing with this error code.

BadPathName OpenError

On Windows, file paths cannot contain these characters: '/', '*', '?', '"', '<', '>', '|'

DeviceBusy OpenError
EndOfBuffer Error
FileBusy OpenError

One of these three things:

  • pathname refers to an executable image which is currently being executed and write access was requested.
  • pathname refers to a file that is currently in use as a swap file, and the O_TRUNC flag was specified.
  • pathname refers to a file that is currently being read by the kernel (e.g., for module/firmware loading), and write access was requested.
FileLocksNotSupported OpenError

The underlying filesystem does not support file locks

FileNotFound OpenError

Either:

  • One of the path components does not exist.
  • Cwd was used, but cwd has been deleted.
  • The path associated with the open directory handle has been deleted.
  • On macOS, multiple processes or threads raced to create the same file with O.EXCL set to false.
FileTooBig OpenError

The file is too large to be opened. This error is unreachable for 64-bit targets, as well as when opening directories.

InvalidBuffer Error
InvalidDebugInfo
InvalidElfEndian
InvalidElfMagic
InvalidElfVersion
InvalidUtf8 OpenError

WASI-only; file paths must be valid UTF-8.

InvalidWtf8 OpenError

Windows-only; file paths provided by the user must be valid WTF-8. https://simonsapin.github.io/wtf-8/

IsDir OpenError

The path refers to directory but the DIRECTORY flag was not provided.

LockedMemoryLimitExceeded
MemoryMappingNotSupported
MissingDebugInfo
NameTooLong OpenError

The path exceeded max_path_bytes bytes.

NetworkNotFound OpenError

On Windows, \\server or \\server\share was not found.

NoDevice OpenError
NoSpaceLeft OpenError

A new path cannot be created because the device has no room for the new file. This error is only reachable when the CREAT flag is provided.

NotDir OpenError

A component used as a directory in the path was not, in fact, a directory, or DIRECTORY was specified and the path was not a directory.

OutOfMemory Error
Overflow

The debug info may be valid but this implementation uses memory mapping which limits things to usize. If the target debug info is 64-bit and host is 32-bit, there may be debug info that is not supportable using this method.

PathAlreadyExists OpenError

The path already exists and the CREAT and EXCL flags were provided.

PermissionDenied
PipeBusy OpenError
ProcessFdQuotaExceeded OpenError
SharingViolation OpenError
SymLinkLoop OpenError
SystemFdQuotaExceeded OpenError
SystemResources OpenError

Insufficient kernel memory was available, or the named file is a FIFO and per-user hard limit on memory allocation for pipes has been reached.

Unexpected UnexpectedError

The Operating System returned an undocumented error code.

This error is in theory not possible, but it would be better to handle this error than to invoke undefined behavior.

When this error code is observed, it usually means the Zig Standard Library needs a small patch to add the error code to the error set for the respective function.

UnimplementedDwarfForeignEndian

TODO: implement this and then remove this error code

WouldBlock OpenError

Source Code

Source code
pub const LoadError = error{
    InvalidDebugInfo,
    MissingDebugInfo,
    InvalidElfMagic,
    InvalidElfVersion,
    InvalidElfEndian,
    /// TODO: implement this and then remove this error code
    UnimplementedDwarfForeignEndian,
    /// The debug info may be valid but this implementation uses memory
    /// mapping which limits things to usize. If the target debug info is
    /// 64-bit and host is 32-bit, there may be debug info that is not
    /// supportable using this method.
    Overflow,

    PermissionDenied,
    LockedMemoryLimitExceeded,
    MemoryMappingNotSupported,
} || Allocator.Error || std.fs.File.OpenError || OpenError

Error SetScanError[src]

Errors

anyerror means the error set is known only at runtime.

EndOfBuffer Error
InvalidBuffer Error
InvalidDebugInfo
MissingDebugInfo
OutOfMemory Error
Overflow Error

Source Code

Source code
pub const ScanError = error{
    InvalidDebugInfo,
    MissingDebugInfo,
} || Allocator.Error || std.debug.FixedBufferReader.Error

Functions

Functionload[src]

pub fn load(gpa: Allocator, path: Path, coverage: *Coverage) LoadError!Info

Parameters

path: Path
coverage: *Coverage

Source Code

Source code
pub fn load(gpa: Allocator, path: Path, coverage: *Coverage) LoadError!Info {
    var sections: Dwarf.SectionArray = Dwarf.null_section_array;
    var elf_module = try Dwarf.ElfModule.loadPath(gpa, path, null, null, &sections, null);
    try elf_module.dwarf.populateRanges(gpa);
    var info: Info = .{
        .address_map = .{},
        .coverage = coverage,
    };
    try info.address_map.put(gpa, elf_module.base_address, elf_module);
    return info;
}

Functiondeinit[src]

pub fn deinit(info: *Info, gpa: Allocator) void

Parameters

info: *Info

Source Code

Source code
pub fn deinit(info: *Info, gpa: Allocator) void {
    for (info.address_map.values()) |*elf_module| {
        elf_module.dwarf.deinit(gpa);
    }
    info.address_map.deinit(gpa);
    info.* = undefined;
}

FunctionresolveAddresses[src]

pub fn resolveAddresses( info: *Info, gpa: Allocator, sorted_pc_addrs: []const u64, output: []SourceLocation, ) ResolveAddressesError!void

Given an array of virtual memory addresses, sorted ascending, outputs a corresponding array of source locations.

Parameters

info: *Info
sorted_pc_addrs: []const u64

Asserts the addresses are in ascending order.

output: []SourceLocation

Asserts its length equals length of sorted_pc_addrs.

Source Code

Source code
pub fn resolveAddresses(
    info: *Info,
    gpa: Allocator,
    /// Asserts the addresses are in ascending order.
    sorted_pc_addrs: []const u64,
    /// Asserts its length equals length of `sorted_pc_addrs`.
    output: []SourceLocation,
) ResolveAddressesError!void {
    assert(sorted_pc_addrs.len == output.len);
    if (info.address_map.entries.len != 1) @panic("TODO");
    const elf_module = &info.address_map.values()[0];
    return info.coverage.resolveAddressesDwarf(gpa, sorted_pc_addrs, output, &elf_module.dwarf);
}

Source Code

Source code
//! Cross-platform abstraction for loading debug information into an in-memory
//! format that supports queries such as "what is the source location of this
//! virtual memory address?"
//!
//! Unlike `std.debug.SelfInfo`, this API does not assume the debug information
//! in question happens to match the host CPU architecture, OS, or other target
//! properties.

const std = @import("../std.zig");
const Allocator = std.mem.Allocator;
const Path = std.Build.Cache.Path;
const Dwarf = std.debug.Dwarf;
const assert = std.debug.assert;
const Coverage = std.debug.Coverage;
const SourceLocation = std.debug.Coverage.SourceLocation;

const Info = @This();

/// Sorted by key, ascending.
address_map: std.AutoArrayHashMapUnmanaged(u64, Dwarf.ElfModule),
/// Externally managed, outlives this `Info` instance.
coverage: *Coverage,

pub const LoadError = Dwarf.ElfModule.LoadError;

pub fn load(gpa: Allocator, path: Path, coverage: *Coverage) LoadError!Info {
    var sections: Dwarf.SectionArray = Dwarf.null_section_array;
    var elf_module = try Dwarf.ElfModule.loadPath(gpa, path, null, null, &sections, null);
    try elf_module.dwarf.populateRanges(gpa);
    var info: Info = .{
        .address_map = .{},
        .coverage = coverage,
    };
    try info.address_map.put(gpa, elf_module.base_address, elf_module);
    return info;
}

pub fn deinit(info: *Info, gpa: Allocator) void {
    for (info.address_map.values()) |*elf_module| {
        elf_module.dwarf.deinit(gpa);
    }
    info.address_map.deinit(gpa);
    info.* = undefined;
}

pub const ResolveAddressesError = Coverage.ResolveAddressesDwarfError;

/// Given an array of virtual memory addresses, sorted ascending, outputs a
/// corresponding array of source locations.
pub fn resolveAddresses(
    info: *Info,
    gpa: Allocator,
    /// Asserts the addresses are in ascending order.
    sorted_pc_addrs: []const u64,
    /// Asserts its length equals length of `sorted_pc_addrs`.
    output: []SourceLocation,
) ResolveAddressesError!void {
    assert(sorted_pc_addrs.len == output.len);
    if (info.address_map.entries.len != 1) @panic("TODO");
    const elf_module = &info.address_map.values()[0];
    return info.coverage.resolveAddressesDwarf(gpa, sorted_pc_addrs, output, &elf_module.dwarf);
}