mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Removed the use of temp allocator in backtrace printing.
Added string::bformat.
This commit is contained in:
committed by
Christoffer Lerno
parent
6c7dc2a28e
commit
e755c36ea2
@@ -98,41 +98,34 @@ macro anycast(any v, $Type) @builtin
|
||||
|
||||
fn bool print_backtrace(String message, int backtraces_to_ignore) @if(env::NATIVE_STACKTRACE) => @stack_mem(0x1100; Allocator smem)
|
||||
{
|
||||
Allocator t = allocator::current_temp;
|
||||
TempAllocator* t2 = allocator::top_temp;
|
||||
TempAllocator* new_t = allocator::new_temp_allocator(smem, 0x1000)!!;
|
||||
allocator::current_temp = allocator::top_temp = new_t;
|
||||
defer
|
||||
{
|
||||
allocator::current_temp = t;
|
||||
allocator::top_temp = t2;
|
||||
new_t.free();
|
||||
}
|
||||
void*[256] buffer;
|
||||
void*[] backtraces = backtrace::capture_current(&buffer);
|
||||
backtraces_to_ignore++;
|
||||
BacktraceList? backtrace = backtrace::symbolize_backtrace(tmem, backtraces);
|
||||
if (catch backtrace) return false;
|
||||
if (backtrace.len() <= backtraces_to_ignore) return false;
|
||||
io::eprint("\nERROR: '");
|
||||
io::eprint(message);
|
||||
io::eprintn("'");
|
||||
foreach (i, &trace : backtrace)
|
||||
@stack_mem(2048; Allocator mem)
|
||||
{
|
||||
if (i < backtraces_to_ignore) continue;
|
||||
String inline_suffix = trace.is_inline ? " [inline]" : "";
|
||||
if (trace.is_unknown())
|
||||
BacktraceList? backtrace = backtrace::symbolize_backtrace(mem, backtraces);
|
||||
if (catch backtrace) return false;
|
||||
if (backtrace.len() <= backtraces_to_ignore) return false;
|
||||
io::eprint("\nERROR: '");
|
||||
io::eprint(message);
|
||||
io::eprintn("'");
|
||||
foreach (i, &trace : backtrace)
|
||||
{
|
||||
io::eprintfn(" in ???%s", inline_suffix);
|
||||
continue;
|
||||
if (i < backtraces_to_ignore) continue;
|
||||
String inline_suffix = trace.is_inline ? " [inline]" : "";
|
||||
if (trace.is_unknown())
|
||||
{
|
||||
io::eprintfn(" in ???%s", inline_suffix);
|
||||
continue;
|
||||
}
|
||||
if (trace.has_file())
|
||||
{
|
||||
io::eprintfn(" in %s (%s:%d) [%s]%s", trace.function, trace.file, trace.line, trace.object_file, inline_suffix);
|
||||
continue;
|
||||
}
|
||||
io::eprintfn(" in %s (source unavailable) [%s]%s", trace.function, trace.object_file, inline_suffix);
|
||||
}
|
||||
if (trace.has_file())
|
||||
{
|
||||
io::eprintfn(" in %s (%s:%d) [%s]%s", trace.function, trace.file, trace.line, trace.object_file, inline_suffix);
|
||||
continue;
|
||||
}
|
||||
io::eprintfn(" in %s (source unavailable) [%s]%s", trace.function, trace.object_file, inline_suffix);
|
||||
}
|
||||
};
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ import std::math;
|
||||
|
||||
const MAX_MEMORY_ALIGNMENT = 0x1000_0000;
|
||||
const DEFAULT_MEM_ALIGNMENT = (void*.alignof) * 2;
|
||||
const ulong KB = 1024;
|
||||
const ulong MB = KB * 1024;
|
||||
const ulong GB = MB * 1024;
|
||||
const ulong TB = GB * 1024;
|
||||
|
||||
faultdef OUT_OF_MEMORY, INVALID_ALLOC_SIZE;
|
||||
|
||||
|
||||
@@ -107,6 +107,19 @@ fn String format(Allocator allocator, String fmt, args...) @format(1) => @pool()
|
||||
return str.copy_str(allocator);
|
||||
}
|
||||
|
||||
<*
|
||||
Return a new String created using the formatting function.
|
||||
|
||||
@param [inout] buffer : `The buffer to use`
|
||||
@param [in] fmt : `The formatting string`
|
||||
*>
|
||||
fn String bformat(char[] buffer, String fmt, args...) @format(1)
|
||||
{
|
||||
DString str = dstring::new_with_capacity(allocator::wrap(buffer), fmt.len + args.len * 8);
|
||||
str.appendf(fmt, ...args);
|
||||
return str.str_view();
|
||||
}
|
||||
|
||||
<*
|
||||
Return a temporary String created using the formatting function.
|
||||
|
||||
|
||||
@@ -115,10 +115,10 @@ fn bool clear_var(String name) => @pool()
|
||||
$endswitch
|
||||
}
|
||||
|
||||
fn String? executable_path(Allocator allocator)
|
||||
fn String? executable_path()
|
||||
{
|
||||
$if env::DARWIN:
|
||||
return darwin::executable_path(allocator);
|
||||
return darwin::executable_path();
|
||||
$else
|
||||
return NOT_FOUND?;
|
||||
$endif
|
||||
|
||||
@@ -130,70 +130,76 @@ fn ulong? elf_module_image_base(String path) @local
|
||||
|
||||
fn void? backtrace_add_from_exec(Allocator allocator, BacktraceList* list, void* addr) @local
|
||||
{
|
||||
char[] buf = mem::talloc_array(char, 1024);
|
||||
|
||||
String exec_path = process::execute_stdout_to_buffer(buf, {"realpath", "-e", string::tformat("/proc/%d/exe", posix::getpid())})!;
|
||||
char[1024] buf @noinit;
|
||||
String exec_path = process::execute_stdout_to_buffer(&buf, {"realpath", "-e", string::bformat(&&(char[64]){}, "/proc/%d/exe", posix::getpid())})!;
|
||||
String obj_name = exec_path.copy(allocator);
|
||||
String addr2line = process::execute_stdout_to_buffer(buf, {"addr2line", "-p", "-i", "-C", "-f", "-e", exec_path, string::tformat("0x%x", addr)})!;
|
||||
String addr2line = process::execute_stdout_to_buffer(&buf, {"addr2line", "-p", "-i", "-C", "-f", "-e", exec_path, string::bformat(&&(char[64]){}, "0x%x", addr)})!;
|
||||
return backtrace_add_addr2line(allocator, list, addr, addr2line, obj_name, "???");
|
||||
}
|
||||
|
||||
fn void? backtrace_add_from_dlinfo(Allocator allocator, BacktraceList* list, void* addr, Linux_Dl_info* info) @local
|
||||
{
|
||||
char[] buf = mem::talloc_array(char, 1024);
|
||||
char[1024] buf @noinit;
|
||||
|
||||
void* obj_addr = addr - (uptr)info.dli_fbase + (uptr)elf_module_image_base(info.dli_fname.str_view())!;
|
||||
ZString obj_path = info.dli_fname;
|
||||
String sname = info.dli_sname ? info.dli_sname.str_view() : "???";
|
||||
String addr2line = process::execute_stdout_to_buffer(buf, {"addr2line", "-p", "-i", "-C", "-f", "-e", obj_path.str_view(), string::tformat("0x%x", obj_addr - 1)})!;
|
||||
String addr2line = process::execute_stdout_to_buffer(&buf, {"addr2line", "-p", "-i", "-C", "-f", "-e", obj_path.str_view(), string::bformat(&&(char[64]){}, "0x%x", obj_addr - 1)})!;
|
||||
return backtrace_add_addr2line(allocator, list, addr, addr2line, info.dli_fname.str_view(), sname);
|
||||
}
|
||||
|
||||
fn Backtrace? backtrace_line_parse(Allocator allocator, String string, String obj_name, String func_name, bool is_inlined)
|
||||
{
|
||||
String[] parts = string.trim().tsplit(" at ");
|
||||
if (parts.len != 2) return NOT_FOUND?;
|
||||
|
||||
uint line = 0;
|
||||
String source = "";
|
||||
if (!parts[1].contains("?") && parts[1].contains(":"))
|
||||
@stack_mem(256; Allocator mem)
|
||||
{
|
||||
usz index = parts[1].rindex_of_char(':')!;
|
||||
source = parts[1][:index];
|
||||
line = parts[1][index + 1..].to_uint()!;
|
||||
}
|
||||
return {
|
||||
.function = parts[0].copy(allocator),
|
||||
.object_file = obj_name.copy(allocator),
|
||||
.file = source.copy(allocator),
|
||||
.line = line,
|
||||
.allocator = allocator,
|
||||
.is_inline = is_inlined
|
||||
String[] parts = string.trim().split(mem, " at ");
|
||||
if (parts.len != 2) return NOT_FOUND?;
|
||||
|
||||
uint line = 0;
|
||||
String source = "";
|
||||
if (!parts[1].contains("?") && parts[1].contains(":"))
|
||||
{
|
||||
usz index = parts[1].rindex_of_char(':')!;
|
||||
source = parts[1][:index];
|
||||
line = parts[1][index + 1..].to_uint()!;
|
||||
}
|
||||
return {
|
||||
.function = parts[0].copy(allocator),
|
||||
.object_file = obj_name.copy(allocator),
|
||||
.file = source.copy(allocator),
|
||||
.line = line,
|
||||
.allocator = allocator,
|
||||
.is_inline = is_inlined
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
fn void? backtrace_add_addr2line(Allocator allocator, BacktraceList* list, void* addr, String addr2line, String obj_name, String func_name) @local
|
||||
{
|
||||
String[] inline_parts = addr2line.tsplit("(inlined by)");
|
||||
usz last = inline_parts.len - 1;
|
||||
foreach (i, part : inline_parts)
|
||||
@stack_mem(1024; Allocator mem)
|
||||
{
|
||||
bool is_inline = i != last;
|
||||
Backtrace? trace = backtrace_line_parse(allocator, part, obj_name, func_name, is_inline);
|
||||
if (catch trace)
|
||||
String[] inline_parts = addr2line.split(mem, "(inlined by)");
|
||||
usz last = inline_parts.len - 1;
|
||||
foreach (i, part : inline_parts)
|
||||
{
|
||||
list.push({
|
||||
.function = func_name.copy(allocator),
|
||||
.object_file = obj_name.copy(allocator),
|
||||
.offset = (uptr)addr,
|
||||
.file = "".copy(allocator),
|
||||
.line = 0,
|
||||
.allocator = allocator,
|
||||
.is_inline = is_inline
|
||||
});
|
||||
continue;
|
||||
bool is_inline = i != last;
|
||||
Backtrace? trace = backtrace_line_parse(allocator, part, obj_name, func_name, is_inline);
|
||||
if (catch trace)
|
||||
{
|
||||
list.push({
|
||||
.function = func_name.copy(allocator),
|
||||
.object_file = obj_name.copy(allocator),
|
||||
.offset = (uptr)addr,
|
||||
.file = "".copy(allocator),
|
||||
.line = 0,
|
||||
.allocator = allocator,
|
||||
.is_inline = is_inline
|
||||
});
|
||||
continue;
|
||||
}
|
||||
list.push(trace);
|
||||
}
|
||||
list.push(trace);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn void? backtrace_add_element(Allocator allocator, BacktraceList *list, void* addr) @local
|
||||
@@ -204,15 +210,12 @@ fn void? backtrace_add_element(Allocator allocator, BacktraceList *list, void* a
|
||||
return;
|
||||
}
|
||||
|
||||
@pool()
|
||||
Linux_Dl_info info;
|
||||
if (dladdr(addr, &info) == 0)
|
||||
{
|
||||
Linux_Dl_info info;
|
||||
if (dladdr(addr, &info) == 0)
|
||||
{
|
||||
return backtrace_add_from_exec(allocator, list, addr);
|
||||
}
|
||||
return backtrace_add_from_dlinfo(allocator, list, addr, &info);
|
||||
};
|
||||
return backtrace_add_from_exec(allocator, list, addr);
|
||||
}
|
||||
return backtrace_add_from_dlinfo(allocator, list, addr, &info);
|
||||
}
|
||||
|
||||
fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace)
|
||||
@@ -227,12 +230,9 @@ fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace)
|
||||
}
|
||||
list.free();
|
||||
}
|
||||
@pool()
|
||||
foreach (addr : backtrace)
|
||||
{
|
||||
foreach (addr : backtrace)
|
||||
{
|
||||
backtrace_add_element(allocator, &list, addr)!;
|
||||
}
|
||||
};
|
||||
backtrace_add_element(allocator, &list, addr)!;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -79,19 +79,26 @@ alias Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info;
|
||||
extern fn void mach_timebase_info(Darwin_mach_timebase_info_data_t* timebase);
|
||||
extern fn ulong mach_absolute_time();
|
||||
|
||||
fn String? executable_path(Allocator allocator)
|
||||
fn String? executable_path()
|
||||
{
|
||||
char[4096] path;
|
||||
uint len = path.len;
|
||||
if (darwin_NSGetExecutablePath(&path, &len) < 0) return NOT_FOUND?;
|
||||
return ((ZString)&path).copy(allocator);
|
||||
static char[4096] path;
|
||||
static uint len = 0;
|
||||
if (!len)
|
||||
{
|
||||
char[4096] buf;
|
||||
uint temp_len = buf.len;
|
||||
if (darwin_NSGetExecutablePath(&buf, &temp_len) < 0) return NOT_FOUND?;
|
||||
path[:temp_len] = buf[:temp_len];
|
||||
len = temp_len;
|
||||
}
|
||||
return (String)path[:len];
|
||||
}
|
||||
|
||||
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?!;
|
||||
String path = env::executable_path() ?? backtrace::EXECUTABLE_PATH_NOT_FOUND?!;
|
||||
uint dyld_count = darwin::_dyld_image_count();
|
||||
for (uint i = 0; i < dyld_count; i++)
|
||||
{
|
||||
@@ -103,23 +110,22 @@ fn uptr? load_address() @local
|
||||
return backtrace::IMAGE_NOT_FOUND?;
|
||||
}
|
||||
|
||||
|
||||
fn Backtrace? backtrace_load_element(Allocator allocator, String execpath, void* buffer, void* load_address) @local
|
||||
{
|
||||
@pool()
|
||||
if (buffer)
|
||||
{
|
||||
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(" ");
|
||||
char[1024] buf;
|
||||
String s = process::execute_stdout_to_buffer(&buf,
|
||||
{ "atos", "-o", execpath, "-arch", env::AARCH64 ? "arm64" : "x86_64", "-l",
|
||||
string::bformat(&&(char[64]){}, "%p", load_address),
|
||||
string::bformat(&&(char[64]){}, "%p", buffer - 1),
|
||||
"-fullPath" })!;
|
||||
@stack_mem(512; Allocator mem)
|
||||
{
|
||||
String[] parts = s.split(mem, " ", 5);
|
||||
if (parts.len == 4)
|
||||
{
|
||||
String[] path_parts = parts[3].tsplit(":");
|
||||
String[] path_parts = parts[3].split(mem, ":");
|
||||
return {
|
||||
.offset = (uptr)buffer,
|
||||
.function = parts[0].copy(allocator),
|
||||
@@ -129,17 +135,17 @@ fn Backtrace? backtrace_load_element(Allocator allocator, String execpath, void*
|
||||
.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
|
||||
};
|
||||
}
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
@@ -156,14 +162,11 @@ fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace)
|
||||
}
|
||||
list.free();
|
||||
}
|
||||
@pool()
|
||||
String execpath = executable_path()!;
|
||||
foreach (addr : backtrace)
|
||||
{
|
||||
String execpath = executable_path(tmem)!;
|
||||
foreach (addr : backtrace)
|
||||
{
|
||||
list.push(backtrace_load_element(allocator, execpath, addr, load_addr) ?? backtrace::BACKTRACE_UNKNOWN);
|
||||
}
|
||||
};
|
||||
list.push(backtrace_load_element(allocator, execpath, addr, load_addr) ?? backtrace::BACKTRACE_UNKNOWN);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
module std::os::posix @if(env::POSIX);
|
||||
|
||||
extern ZString* environ;
|
||||
|
||||
extern fn CLong sysconf(CInt name);
|
||||
|
||||
const CInt _SC_PAGESIZE @if(env::LINUX) = 30;
|
||||
const CInt _SC_PAGESIZE @if(env::DARWIN) = 29;
|
||||
|
||||
28
lib/std/os/posix/mman.c3
Normal file
28
lib/std/os/posix/mman.c3
Normal file
@@ -0,0 +1,28 @@
|
||||
module std::os::posix @if(env::POSIX);
|
||||
import libc;
|
||||
|
||||
|
||||
const PROT_NONE = 0x00; // no permissions
|
||||
const PROT_READ = 0x01; // pages can be read
|
||||
const PROT_WRITE = 0x02; // pages can be written
|
||||
const PROT_EXEC = 0x04; // pages can be executed
|
||||
|
||||
const MAP_SHARED = 0x0001; // share changes
|
||||
const MAP_PRIVATE = 0x0002; // changes are private
|
||||
|
||||
const MAP_FILE = 0x0000; // map from file (default)
|
||||
const MAP_ANONYMOUS = 0x1000; // allocated from memory, swap space
|
||||
|
||||
const void* MAP_FAILED = (void *)(uptr)-1; // mmap failed
|
||||
const MADV_NORMAL = 0; // no further special treatment
|
||||
const MADV_RANDOM = 1; // expect random page refs
|
||||
const MADV_SEQUENTIAL = 2; // expect sequential page refs
|
||||
const MADV_WILLNEED = 3; // will need these pages
|
||||
const MADV_DONTNEED = 4; // dont need these pages
|
||||
|
||||
extern fn void* mmap(void*, usz, CInt, CInt, CInt, Off_t);
|
||||
extern fn CInt munmap(void*, usz);
|
||||
extern fn CInt mprotect(void*, usz, CInt);
|
||||
extern fn int madvise(void*, usz, CInt);
|
||||
|
||||
extern fn CInt getpagesize();
|
||||
@@ -55,21 +55,18 @@ fn void? create_named_pipe_helper(void** rd, void **wr) @local @if(env::WIN32)
|
||||
|
||||
tlocal long index = 0;
|
||||
long unique = index++;
|
||||
@pool()
|
||||
{
|
||||
String s = string::tformat(`\\.\pipe\c3_subprocess.%08x.%08x.%d`, win32::getCurrentProcessId(), win32::getCurrentThreadId(), unique);
|
||||
Win32_LPCSTR str = (Win32_LPCSTR)s.ptr;
|
||||
*rd = win32::createNamedPipeA(
|
||||
str,
|
||||
win32::PIPE_ACCESS_INBOUND | win32::FILE_FLAG_OVERLAPPED,
|
||||
win32::PIPE_TYPE_BYTE | win32::PIPE_WAIT,
|
||||
1, 4096, 4096, 0, &sa_attr);
|
||||
if (win32::INVALID_HANDLE_VALUE == *rd) return FAILED_TO_CREATE_PIPE?;
|
||||
*wr = win32::createFileA(
|
||||
str, win32::GENERIC_WRITE, 0, &sa_attr,
|
||||
win32::OPEN_EXISTING, win32::FILE_ATTRIBUTE_NORMAL, null);
|
||||
if (win32::INVALID_HANDLE_VALUE == *wr) return FAILED_TO_CREATE_PIPE?;
|
||||
};
|
||||
String s = string::bformat(&&(char[128]){}, `\\.\pipe\c3_subprocess.%08x.%08x.%d`, win32::getCurrentProcessId(), win32::getCurrentThreadId(), unique);
|
||||
Win32_LPCSTR str = (Win32_LPCSTR)s.ptr;
|
||||
*rd = win32::createNamedPipeA(
|
||||
str,
|
||||
win32::PIPE_ACCESS_INBOUND | win32::FILE_FLAG_OVERLAPPED,
|
||||
win32::PIPE_TYPE_BYTE | win32::PIPE_WAIT,
|
||||
1, 4096, 4096, 0, &sa_attr);
|
||||
if (win32::INVALID_HANDLE_VALUE == *rd) return FAILED_TO_CREATE_PIPE?;
|
||||
*wr = win32::createFileA(
|
||||
str, win32::GENERIC_WRITE, 0, &sa_attr,
|
||||
win32::OPEN_EXISTING, win32::FILE_ATTRIBUTE_NORMAL, null);
|
||||
if (win32::INVALID_HANDLE_VALUE == *wr) return FAILED_TO_CREATE_PIPE?;
|
||||
}
|
||||
|
||||
fn WString convert_command_line_win32(String[] command_line) @inline @if(env::WIN32) @local
|
||||
@@ -143,12 +140,12 @@ fn SubProcess? create(String[] command_line, SubProcessOptions options = {}, Str
|
||||
if (!win32::setHandleInformation(wr, win32::HANDLE_FLAG_INHERIT, 0)) return FAILED_TO_CREATE_PIPE?;
|
||||
}
|
||||
|
||||
@pool()
|
||||
@stack_mem(2048; Allocator mem)
|
||||
{
|
||||
WString used_environment = null;
|
||||
if (!options.inherit_environment)
|
||||
{
|
||||
DString env = dstring::temp_with_capacity(64);
|
||||
DString env = dstring::new_with_capacity(mem, 64);
|
||||
if (!environment.len)
|
||||
{
|
||||
env.append("\0");
|
||||
@@ -159,7 +156,7 @@ fn SubProcess? create(String[] command_line, SubProcessOptions options = {}, Str
|
||||
env.append("\0");
|
||||
}
|
||||
env.append("\0");
|
||||
used_environment = env.str_view().to_temp_wstring()!;
|
||||
used_environment = env.str_view().to_wstring(mem)!;
|
||||
}
|
||||
|
||||
// Handle stdin pipe if not inheriting
|
||||
@@ -266,26 +263,26 @@ fn SubProcess? create(String[] command_line, SubProcessOptions options = {}, Str
|
||||
<*
|
||||
@require command_line.len > 0
|
||||
*>
|
||||
fn ZString* tcopy_command_line(String[] command_line) @local @inline @if(env::POSIX)
|
||||
fn ZString* copy_command_line(Allocator mem, String[] command_line) @local @inline @if(env::POSIX)
|
||||
{
|
||||
ZString* copy = mem::talloc_array(ZString, command_line.len + 1);
|
||||
ZString* copy = allocator::alloc_array(mem, ZString, command_line.len + 1);
|
||||
foreach (i, str : command_line)
|
||||
{
|
||||
copy[i] = str.zstr_tcopy();
|
||||
copy[i] = str.zstr_copy(mem);
|
||||
}
|
||||
copy[command_line.len] = null;
|
||||
return copy;
|
||||
}
|
||||
|
||||
const ZString[1] EMPTY_ENVIRONMENT @if(env::POSIX) = { null };
|
||||
fn ZString* tcopy_env(String[] environment) @local @inline @if(env::POSIX)
|
||||
fn ZString* copy_env(Allocator mem, String[] environment) @local @inline @if(env::POSIX)
|
||||
{
|
||||
if (!environment.len) return &EMPTY_ENVIRONMENT;
|
||||
ZString* copy = mem::talloc_array(ZString, environment.len + 1);
|
||||
ZString* copy = allocator::alloc_array(mem, ZString, environment.len + 1);
|
||||
copy[environment.len] = null;
|
||||
foreach (i, str : environment)
|
||||
{
|
||||
copy[i] = str.zstr_tcopy();
|
||||
copy[i] = str.zstr_copy(mem);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
@@ -338,10 +335,10 @@ fn SubProcess? create(String[] command_line, SubProcessOptions options = {}, Str
|
||||
}
|
||||
|
||||
Pid_t child;
|
||||
@pool()
|
||||
@stack_mem(2048; Allocator mem)
|
||||
{
|
||||
ZString* command_line_copy = tcopy_command_line(command_line);
|
||||
ZString* used_environment = options.inherit_environment ? posix::environ : tcopy_env(environment);
|
||||
ZString* command_line_copy = copy_command_line(mem, command_line);
|
||||
ZString* used_environment = options.inherit_environment ? posix::environ : copy_env(mem, environment);
|
||||
if (options.search_user_path)
|
||||
{
|
||||
if (posix::spawnp(&child, command_line_copy[0], &actions, null, command_line_copy, used_environment)) return FAILED_TO_START_PROCESS?;
|
||||
|
||||
41
lib/std/os/win32/memoryapi.c3
Normal file
41
lib/std/os/win32/memoryapi.c3
Normal file
@@ -0,0 +1,41 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
|
||||
enum Win32_AllocationType : const Win32_DWORD
|
||||
{
|
||||
MEM_COMMIT = 0x00001000,
|
||||
MEM_RESERVE = 0x00002000,
|
||||
MEM_RESET = 0x00080000,
|
||||
MEM_RESET_UNDO = 0x01000000,
|
||||
MEM_LARGE_PAGES = 0x20000000,
|
||||
MEM_PHYSICAL = 0x00400000,
|
||||
MEM_TOP_DOWN = 0x00100000,
|
||||
MEM_WRITE_WATCH = 0x00200000
|
||||
}
|
||||
|
||||
enum Win32_Protect : const Win32_DWORD
|
||||
{
|
||||
PAGE_EXECUTE = 0x10,
|
||||
PAGE_EXECUTE_READ = 0x20,
|
||||
PAGE_EXECUTE_READWRITE = 0x40,
|
||||
PAGE_EXECUTE_WRITECOPY = 0x80,
|
||||
PAGE_NOACCESS = 0x01,
|
||||
PAGE_READONLY = 0x02,
|
||||
PAGE_READWRITE = 0x04,
|
||||
PAGE_WRITECOPY = 0x08,
|
||||
PAGE_TARGETS_INVALID = 0x40000000,
|
||||
PAGE_TARGETS_NO_UPDATE = 0x40000000,
|
||||
PAGE_GUARD = 0x100,
|
||||
PAGE_NOCACHE = 0x200,
|
||||
PAGE_WRITECOMBINE = 0x400,
|
||||
}
|
||||
|
||||
enum Win32_FreeType : const Win32_DWORD
|
||||
{
|
||||
MEM_DECOMMIT = 0x00004000,
|
||||
MEM_RELEASE = 0x00008000,
|
||||
MEM_COALESCE_PLACEHOLDERS = 0x00000001,
|
||||
MEM_PRESERVE_PLACEHOLDER = 0x00000002,
|
||||
}
|
||||
extern fn Win32_LPVOID virtualAlloc(Win32_LPVOID lpAddres, Win32_SIZE_T dwSize, Win32_AllocationType flAllocationType, Win32_DWORD flProtect) @extern("VirtualAlloc");
|
||||
extern fn Win32_PVOID virtualAlloc2(Win32_HANDLE process, Win32_PVOID baseAddress, Win32_SIZE_T size, Win32_AllocationType allocationType, Win32_ULONG pageProtection, Win32_MEM_EXTENDED_PARAMETER* extendedParameters, Win32_ULONG parameterCount) @extern("VirtualAlloc2");
|
||||
extern fn Win32_BOOL virtualFree(Win32_LPVOID lpAddress, Win32_SIZE_T dwSize, Win32_FreeType dwFreeType) @extern("VirtualFree");
|
||||
37
lib/std/os/win32/winnt.c3
Normal file
37
lib/std/os/win32/winnt.c3
Normal file
@@ -0,0 +1,37 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
|
||||
enum Win32_MEM_EXTENDED_PARAMETER_TYPE : CInt
|
||||
{
|
||||
INVALID_TYPE,
|
||||
ADDRESS_REQUIREMENTS,
|
||||
NUMA_NODE,
|
||||
PARTITION_HANDLE,
|
||||
USER_PHYSICAL_HANDLE,
|
||||
ATTRIBUTE_FLAGS,
|
||||
IMAGE_MACHINE,
|
||||
MAX
|
||||
}
|
||||
alias Win32_PMEM_EXTENDED_PARAMETER_TYPE = Win32_MEM_EXTENDED_PARAMETER_TYPE;
|
||||
|
||||
enum Win32_MEM_EXTENDED_PARAMETER_ATTRIBUTE : const Win32_DWORD64
|
||||
{
|
||||
NONPAGED = 0x02, // The allocation is non-pageable.
|
||||
NONPAGED_LARGE = 0x08, // The allocation is mapped using large pages.
|
||||
NONPAGED_HUGE = 0x10, // The allocation is mapped using huge pages.
|
||||
EC_CODE = 0x40, // The allocation will contain emulation-compatible (EC) code.
|
||||
}
|
||||
|
||||
struct Win32_MEM_EXTENDED_PARAMETER
|
||||
{
|
||||
Win32_MEM_EXTENDED_PARAMETER_TYPE type;
|
||||
union
|
||||
{
|
||||
Win32_MEM_EXTENDED_PARAMETER_ATTRIBUTE attribute; // If type is ATTRIBUTE_FLAGS
|
||||
Win32_DWORD64 nodeNumber; // If type is NUMA_NODE
|
||||
Win32_PVOID pointer; // If type is ADDRESS_REQUIREMENTS
|
||||
Win32_SIZE_T size;
|
||||
Win32_HANDLE handle;
|
||||
Win32_DWORD uLong;
|
||||
}
|
||||
}
|
||||
alias Win32_PMEM_EXTENDED_PARAMETER = Win32_MEM_EXTENDED_PARAMETER*;
|
||||
@@ -17,6 +17,7 @@
|
||||
- Update error message for struct initialization #2286
|
||||
- `$is_const` is deprecated in favour of `@is_const` based on `$defined`.
|
||||
- Multiline contract comments #2113
|
||||
- Removed the use of temp allocator in backtrace printing.
|
||||
|
||||
### Fixes
|
||||
- mkdir/rmdir would not work properly with substring paths on non-windows platforms.
|
||||
@@ -52,6 +53,7 @@
|
||||
### Stdlib changes
|
||||
- Improve contract for readline. #2280
|
||||
- Added Whirlpool hash.
|
||||
- Added string::bformat.
|
||||
|
||||
## 0.7.3 Change list
|
||||
|
||||
|
||||
@@ -681,8 +681,7 @@ no_match: ; preds = %compare
|
||||
!72 = !DILocation(line: 35, column: 49, scope: !66)
|
||||
!73 = !DILocalVariable(name: "name", arg: 3, scope: !66, file: !7, line: 35, type: !39)
|
||||
!74 = !DILocation(line: 35, column: 63, scope: !66)
|
||||
!75 = !DILocation(line: 709, column: 18, scope: !76, inlinedAt: !78)
|
||||
!76 = distinct !DISubprogram(name: "new", linkageName: "new", scope: !77, file: !77, line: 706, scopeLine: 706, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6)
|
||||
!76 = distinct !DISubprogram(name: "new", linkageName: "new", scope: !77, file: !77, line: 710, scopeLine: 710, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6)
|
||||
!77 = !DIFile(filename: "mem.c3", directory:
|
||||
!78 = !DILocation(line: 37, column: 9, scope: !66)
|
||||
!79 = distinct !DISubprogram(name: "test", linkageName: "test.test", scope: !7, file: !7, line: 45, type: !80, scopeLine: 45, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !21)
|
||||
|
||||
Reference in New Issue
Block a user