# nim c -r --debugger:native --stacktrace:off -d:nimStackTraceOverride import libbacktrace import strutils, os proc test() = raise newException(ValueError, "Value error") proc test2() = test() proc test3() = test2() type DlPhdrInfo = object dlpiAddr: uint # Base address of object dlpiName: cstring # (Null-terminated) name of object dlpiPhdr: ptr UncheckedArray[uint] # Pointer to array of ELF program headers for this object dlpiPhnum: uint16 # Number of items in dlpi_phdr # The following fields were added in glibc 2.4, after the first # version of this structure was available. Check the size # argument passed to the dl_iterate_phdr callback to determine # whether or not each later member is available. dlpiAdds: culonglong # Incremented when a new object may have been added dlpiSubs: culonglong # Incremented when an object may have been removed dlpiTlsModid: csizet #If there is a PT_TLS segment, its module ID as used in TLS relocations, else zero dlpiTlsData: pointer # The address of the calling thread's instance # of this module's PT_TLS segment, if it has # one and it has been allocated in the calling # thread, otherwise a null pointer DlInfo = object dli_fname: cstring # Pathname of shared object that contains address dli_fbase: pointer # Base address at which shared object is loaded dli_sname: cstring # Name of symbol whose definition overlaps addr dli_saddr: pointer # Exact address of symbol named in dli_sname PhdrCallback = proc (info: ptr DlPhdrInfo, size: csizet, data: pointer): cint {.cdecl.} proc dlIteratePhdr(cb: PhdrCallback, data: pointer): cint {.importc: "dl_iterate_phdr".} proc dladdr(address: pointer, info: ptr DlInfo): cint {.importc.} proc callback(info: ptr DlPhdrInfo, size: csizet, data: pointer): cint {.cdecl.} = echo info.dlpiName, ": ", info.dlpiAddr.toHex proc NimMain() {.importc.} proc get() = try: test3() except ValueError as e: #let traceE = getStackTraceEntries(e) #echo traceE.repr let trace = getProgramCounters(128) #echo trace.repr echo dlIteratePhdr(callback, nil) var nimMainInfo: DlInfo info: DlInfo discard dladdr(cast[pointer](NimMain), nimMainInfo.addr) for counter in trace: #let counter = counter3.programCounter if dladdr(cast[pointer](counter), info.addr) != 0 and info.dliFbase == nimMainInfo.dliFbase: #echo info.repr echo counter - cast[uint](info.dliFbase) #echo getDebuggingInfo(trace, 128) #echo dladdr(cast[pointer](trace[0].programCounter), info.addr) #echo info.dliFname #echo cast[uint](info.dliFbase) #echo trace[0].programCounter #echo trace[0].programCounter - cast[uint](info.dliFbase) #raise if fileExists("traceinfo"): echo "Here" var trace: typeof(getProgramCounters(128)) var nimMainInfo: DlInfo discard dladdr(cast[pointer](NimMain), nimMainInfo.addr) for counter in "traceinfo".lines: echo counter trace.add cast[uint](nimMainInfo.dliFbase) + counter.parseInt.uint echo trace for info in getDebuggingInfo(trace, 128): echo info.repr else: get()