mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
- Remove `[?]` syntax. - Change `int!` to `int?` syntax. - New `fault` declarations. - Enum associated values can reference the calling enum.
158 lines
5.5 KiB
Plaintext
158 lines
5.5 KiB
Plaintext
module std::os::darwin @if(env::DARWIN);
|
|
import std::collections::list, std::os;
|
|
|
|
const CTL_UNSPEC = 0; /* unused */
|
|
const CTL_KERN = 1; /* "high kernel": proc, limits */
|
|
const CTL_VM = 2; /* virtual memory */
|
|
const CTL_VFS = 3; /* file system, mount type is next */
|
|
const CTL_NET = 4; /* network, see socket.h */
|
|
const CTL_DEBUG = 5; /* debugging parameters */
|
|
const CTL_HW = 6; /* generic cpu/io */
|
|
const CTL_MACHDEP = 7; /* machine dependent */
|
|
const CTL_USER = 8; /* user-level */
|
|
const CTL_MAXID = 9; /* number of valid top-level ids */
|
|
|
|
const HW_MACHINE = 1; /* string: machine class */
|
|
const HW_MODEL = 2; /* string: specific machine model */
|
|
const HW_NCPU = 3; /* int: number of cpus */
|
|
const HW_BYTEORDER = 4; /* int: machine byte order */
|
|
const HW_PHYSMEM = 5; /* int: total memory */
|
|
const HW_USERMEM = 6; /* int: non-kernel memory */
|
|
const HW_PAGESIZE = 7; /* int: software page size */
|
|
const HW_DISKNAMES = 8; /* strings: disk drive names */
|
|
const HW_DISKSTATS = 9; /* struct: diskstats[] */
|
|
const HW_EPOCH = 10; /* int: 0 for Legacy, else NewWorld */
|
|
const HW_FLOATINGPT = 11; /* int: has HW floating point? */
|
|
const HW_MACHINE_ARCH = 12; /* string: machine architecture */
|
|
const HW_VECTORUNIT = 13; /* int: has HW vector unit? */
|
|
const HW_BUS_FREQ = 14; /* int: Bus Frequency */
|
|
const HW_CPU_FREQ = 15; /* int: CPU Frequency */
|
|
const HW_CACHELINE = 16; /* int: Cache Line Size in Bytes */
|
|
const HW_L1ICACHESIZE = 17; /* int: L1 I Cache Size in Bytes */
|
|
const HW_L1DCACHESIZE = 18; /* int: L1 D Cache Size in Bytes */
|
|
const HW_L2SETTINGS = 19; /* int: L2 Cache Settings */
|
|
const HW_L2CACHESIZE = 20; /* int: L2 Cache Size in Bytes */
|
|
const HW_L3SETTINGS = 21; /* int: L3 Cache Settings */
|
|
const HW_L3CACHESIZE = 22; /* int: L3 Cache Size in Bytes */
|
|
const HW_MAXID = 23; /* number of valid hw ids */
|
|
|
|
extern fn CInt sysctl(CInt *name, CUInt namelen, void *oldp, usz *oldlenp, void *newp, usz newlen);
|
|
extern fn CInt darwin_NSGetExecutablePath(char* buffer, uint *size) @extern("_NSGetExecutablePath") @builtin;
|
|
extern fn Darwin_segment_command_64* getsegbyname(ZString segname);
|
|
extern fn uint _dyld_image_count();
|
|
extern fn ZString _dyld_get_image_name(uint image_index);
|
|
extern fn iptr _dyld_get_image_vmaddr_slide(uint image_index);
|
|
extern fn CInt dladdr(void* addr, Darwin_Dl_info* info);
|
|
|
|
struct Darwin_Dl_info
|
|
{
|
|
ZString dli_fname; /* Pathname of shared object */
|
|
void* dli_fbase; /* Base address of shared object */
|
|
ZString dli_sname; /* Name of nearest symbol */
|
|
void* dli_saddr; /* Address of nearest symbol */
|
|
}
|
|
|
|
struct Darwin_segment_command_64
|
|
{
|
|
uint cmd; /* LC_SEGMENT_64 */
|
|
uint cmdsize; /* includes sizeof section_64 structs */
|
|
char[16] segname; /* segment name */
|
|
ulong vmaddr; /* memory address of this segment */
|
|
ulong vmsize; /* memory size of this segment */
|
|
ulong fileoff; /* file offset of this segment */
|
|
ulong filesize; /* amount to map from the file */
|
|
int maxprot; /* maximum VM protection */
|
|
int initprot; /* initial VM protection */
|
|
uint nsects; /* number of sections in segment */
|
|
uint flags; /* flags */
|
|
}
|
|
|
|
|
|
fn String? executable_path(Allocator allocator)
|
|
{
|
|
char[4096] path;
|
|
uint len = path.len;
|
|
if (darwin_NSGetExecutablePath(&path, &len) < 0) return NOT_FOUND?;
|
|
return ((ZString)&path).copy(allocator);
|
|
}
|
|
|
|
fn uptr? load_address() @local
|
|
{
|
|
Darwin_segment_command_64* cmd = darwin::getsegbyname("__TEXT");
|
|
if (!cmd) return backtrace::SEGMENT_NOT_FOUND?;
|
|
String path = env::executable_path(tmem()) ?? backtrace::EXECUTABLE_PATH_NOT_FOUND?!;
|
|
uint dyld_count = darwin::_dyld_image_count();
|
|
for (uint i = 0; i < dyld_count; i++)
|
|
{
|
|
ZString image_name = darwin::_dyld_get_image_name(i);
|
|
if (!image_name) continue;
|
|
if (image_name.str_view() != path) continue;
|
|
return cmd.vmaddr + darwin::_dyld_get_image_vmaddr_slide(i);
|
|
}
|
|
return backtrace::IMAGE_NOT_FOUND?;
|
|
}
|
|
|
|
|
|
fn Backtrace? backtrace_load_element(String execpath, void* buffer, void* load_address, Allocator allocator = allocator::heap()) @local
|
|
{
|
|
@pool(allocator)
|
|
{
|
|
if (buffer)
|
|
{
|
|
char* buf = tmalloc(1024);
|
|
String s = process::execute_stdout_to_buffer(buf[:1024],
|
|
{ "atos", "-o", execpath, "-arch", env::AARCH64 ? "arm64" : "x86_64", "-l",
|
|
string::tformat("%p", load_address),
|
|
string::tformat("%p", buffer - 1),
|
|
"-fullPath" })!;
|
|
String[] parts = s.tsplit(" ");
|
|
if (parts.len == 4)
|
|
{
|
|
String[] path_parts = parts[3].tsplit(":");
|
|
return {
|
|
.offset = (uptr)buffer,
|
|
.function = parts[0].copy(allocator),
|
|
.object_file = parts[2][..^2].copy(allocator),
|
|
.file = path_parts[0][1..].copy(allocator),
|
|
.line = path_parts[1][..^2].to_uint()!,
|
|
.allocator = allocator
|
|
};
|
|
}
|
|
}
|
|
Darwin_Dl_info info;
|
|
if (!buffer || !darwin::dladdr(buffer, &info)) return backtrace::BACKTRACE_UNKNOWN;
|
|
return {
|
|
.offset = (uptr)buffer,
|
|
.function = info.dli_sname ? info.dli_sname.copy(allocator) : "???".copy(allocator),
|
|
.object_file = info.dli_fname.copy(allocator),
|
|
.file = "".copy(allocator),
|
|
.line = 0,
|
|
.allocator = allocator
|
|
};
|
|
};
|
|
}
|
|
|
|
fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace)
|
|
{
|
|
void *load_addr = (void *)load_address()!;
|
|
BacktraceList list;
|
|
list.init(allocator, backtrace.len);
|
|
defer catch
|
|
{
|
|
foreach (trace : list)
|
|
{
|
|
trace.free();
|
|
}
|
|
list.free();
|
|
}
|
|
@pool(allocator)
|
|
{
|
|
String execpath = executable_path(allocator::temp())!;
|
|
foreach (addr : backtrace)
|
|
{
|
|
list.push(backtrace_load_element(execpath, addr, load_addr, allocator) ?? backtrace::BACKTRACE_UNKNOWN);
|
|
}
|
|
};
|
|
return list;
|
|
}
|