fuck submodules part 3
This commit is contained in:
parent
a1a94dec51
commit
88dee75f7d
26 changed files with 2962 additions and 0 deletions
169
libraries/back/back_linux.odin
Normal file
169
libraries/back/back_linux.odin
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
#+vet explicit-allocators
|
||||
#+private file
|
||||
package back
|
||||
|
||||
@require import "base:runtime"
|
||||
@require import "base:intrinsics"
|
||||
|
||||
@require import "core:c"
|
||||
@require import "core:c/libc"
|
||||
@require import "core:os"
|
||||
@require import "core:strings"
|
||||
|
||||
when !USE_FALLBACK {
|
||||
|
||||
foreign import lib "system:c"
|
||||
|
||||
@(private="package")
|
||||
_Trace_Entry :: rawptr
|
||||
|
||||
@(private="package")
|
||||
_trace :: #force_no_inline proc(buf: Trace) -> (n: int) {
|
||||
// In order to omit this function's frame and the caller, we alloca a temp buffer with 2 extra slots.
|
||||
bigger_buf := ([^]Trace_Entry)(intrinsics.alloca((2 + len(buf)) * size_of(Trace_Entry), align_of(Trace_Entry)))[:len(buf)+2]
|
||||
_n := int(backtrace(raw_data(bigger_buf), i32(len(bigger_buf))))
|
||||
if _n > 2 {
|
||||
copy(buf, bigger_buf[2:])
|
||||
return _n-2
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@(private="package")
|
||||
_lines_destroy :: proc(msgs: []Line, allocator: runtime.Allocator) {
|
||||
for msg in msgs {
|
||||
delete(msg.location, allocator)
|
||||
if msg.symbol != "??OOM" && msg.symbol != "??" { delete(msg.symbol, allocator) }
|
||||
}
|
||||
delete(msgs, allocator)
|
||||
}
|
||||
|
||||
@(private="package")
|
||||
_lines :: proc(bt: Trace, allocator, temp_allocator: runtime.Allocator) -> (out: []Line, err: Lines_Error) {
|
||||
msgs := backtrace_symbols(raw_data(bt), i32(len(bt)))[:len(bt)]
|
||||
defer libc.free(raw_data(msgs))
|
||||
|
||||
out = make([]Line, len(bt), allocator)
|
||||
defer if err != nil { _lines_destroy(out, allocator) }
|
||||
|
||||
// Debug info is needed.
|
||||
when !ODIN_DEBUG {
|
||||
for msg, i in msgs {
|
||||
location, mem_err := strings.clone_from(msg, allocator)
|
||||
if mem_err != nil { return out, .Out_Of_Memory }
|
||||
|
||||
out[i] = Line {
|
||||
location = location,
|
||||
symbol = "??",
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
i := 0
|
||||
|
||||
command := make([dynamic]string, temp_allocator)
|
||||
defer delete(command)
|
||||
|
||||
if _, err := append(&command, ADDR2LINE_PATH, "--functions", "--exe", ""); err != nil { return out, .Out_Of_Memory }
|
||||
|
||||
COMMAND_EXE_POS :: 3
|
||||
COMMAND_START_LEN :: 4
|
||||
|
||||
for msg in msgs {
|
||||
exe, addr := parse_address(msg) or_return
|
||||
if command[COMMAND_EXE_POS] == "" {
|
||||
command[COMMAND_EXE_POS] = exe
|
||||
} else if command[COMMAND_EXE_POS] != exe {
|
||||
i += exec_and_fill(command[:], out[i:], msgs[i:], allocator, temp_allocator) or_return
|
||||
|
||||
command[COMMAND_EXE_POS] = exe
|
||||
resize(&command, COMMAND_START_LEN)
|
||||
}
|
||||
|
||||
if _, err := append(&command, addr); err != nil { return out, .Out_Of_Memory }
|
||||
}
|
||||
|
||||
if len(command) > COMMAND_START_LEN {
|
||||
i += exec_and_fill(command[:], out[i:], msgs[i:], allocator, temp_allocator) or_return
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
// Parses the exe and address out of a backtrace line.
|
||||
// Example: .../main(+0x20) [0x100000] -> .../main, +0x20, nil
|
||||
parse_address :: proc(cmsg: cstring) -> (string, string, Lines_Error) {
|
||||
msg := string(cmsg)
|
||||
close_idx := strings.last_index_byte(msg, ')')
|
||||
if close_idx < 1 {
|
||||
return "", "", .Parse_Address_Fail
|
||||
}
|
||||
|
||||
open_idx := strings.last_index_byte(msg[:close_idx], '(')
|
||||
if open_idx < 0 {
|
||||
return "", "", .Parse_Address_Fail
|
||||
}
|
||||
|
||||
return msg[:open_idx], msg[open_idx+1:close_idx], nil
|
||||
}
|
||||
|
||||
exec_and_fill :: proc(command: []string, out: []Line, msgs: []cstring, allocator, temp_allocator: runtime.Allocator) -> (filled: int, err: Lines_Error) {
|
||||
state, stdout, stderr, perr := os.process_exec({command = command}, temp_allocator)
|
||||
defer delete(stdout, temp_allocator)
|
||||
defer delete(stderr, temp_allocator)
|
||||
|
||||
if perr != nil || !state.success {
|
||||
return 0, .Addr2line_Process_Error
|
||||
}
|
||||
|
||||
count := len(command)-COMMAND_START_LEN
|
||||
|
||||
sstdout := string(stdout)
|
||||
for i in 0..<count {
|
||||
out[i].symbol, err = process_line(strings.split_lines_iterator(&sstdout), allocator)
|
||||
if err == .Out_Of_Memory {
|
||||
out[i].symbol = "??OOM"
|
||||
} else if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: parse location and transform to ODIN_ERROR_POS_STYLE
|
||||
out[i].location, err = process_line(strings.split_lines_iterator(&sstdout), allocator)
|
||||
if err == .Out_Of_Memory {
|
||||
out[i].location = "??OOM"
|
||||
} else if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if out[i].location == "" || out[i].location == "??" {
|
||||
fallback, mem_err := strings.clone_from(msgs[i], allocator)
|
||||
if mem_err != nil { return 0, .Out_Of_Memory }
|
||||
out[i].location = fallback
|
||||
}
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
process_line :: proc(line: string, ok: bool, allocator: runtime.Allocator) -> (string, Lines_Error) {
|
||||
if !ok { return "", .Addr2line_Unexpected_EOF }
|
||||
if line == "" { return "", .Addr2line_Output_Error }
|
||||
|
||||
if line == "??" {
|
||||
return "??", nil
|
||||
}
|
||||
|
||||
ret, err := strings.clone(strings.trim_right_space(line), allocator)
|
||||
return ret, err == nil ? nil : .Out_Of_Memory
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreign lib {
|
||||
backtrace :: proc(buffer: [^]rawptr, size: c.int) -> c.int ---
|
||||
backtrace_symbols :: proc(buffer: [^]rawptr, size: c.int) -> [^]cstring ---
|
||||
backtrace_symbols_fd :: proc(buffer: [^]rawptr, size: c.int, fd: ^libc.FILE) ---
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue