Xcode: Lazy variable value not available in debugger - xcode

Why is a lazy variable not available for inspection in the Xcode debugger?
var d: Date? {
return Date()
}
let date = d
// Set breakpoint here
At the breakpoint the variable inspector in Xcode shows value Date? for variable date. When trying to print the description of the variable the lldb console prints:
Printing description of date:
(Date?) date = <variable not available>
Build Settings > Optimization Level is set to -Onone for debug and the scheme's Build Configuration is set to Debug.

Related

lldb debug v8: how to get the v8 the type T value of handle<T> type

I'm debugging v8 using lldb.
How can I print the string inside of Handle<String> Source?
The debug process is as follows:
(lldb) r
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
frame #0: 0x000000010100536b libv8.dylib`v8::internal::Compiler::GetSharedFunctionInfoForScript(isolate=0x0000000118008000, source=Handle<v8::internal::String> # 0x00007ffeefbfd4a0, script_details=0x00007ffeefbfd730, origin_options=(flags_ = 0), extension=0x0000000000000000, cached_data=0x0000000000000000, compile_options=kNoCompileOptions, no_cache_reason=kNoCacheNoReason, natives=NOT_NATIVES_CODE) at compiler.cc:2806:27
2803 MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
2804 solate* isolate, Handle<String> source,
2805 ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
-> 2806 ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
2807
2808 if (compile_options == ScriptCompiler::kNoCompileOptions ||
2809 compile_options == ScriptCompiler::kEagerCompile) {
Target 0: (d8) stopped.
(lldb) p source
(v8::internal::Handle<v8::internal::String>) $9 = {
v8::internal::HandleBase = {
location_ = 0x000000010f009a60
}
}
(lldb) p *$9
(v8::internal::String) $10 = {
v8::internal::TorqueGeneratedString<v8::internal::String, v8::internal::Name> = {
.....
}
}
Take a look at tools/lldb_commands.py. In short: configure your LLDB to load that script:
echo "command script import /path/to/v8/tools/lldb_commands.py" >> ~/.lldbinit
and then use the convenience commands it provides, the most important one being job, a mnemonic for "JavaScript object". It needs the raw pointer value that you'll see as ptr_ = ... somewhere in the output of p *$9, but you don't need to retrieve it manually. Example:
(lldb) job source->ptr_
0x28c008109019: [String]: "console.log('hello world');"
(Side note: tools/gdbinit tends to have a few more features than tools/lldbinit, because most folks on the team use GDB. We'd be happy to accept patches to improve LLDB support; relevant to the case at hand would be gdbinit's jh shortcut (allowing simply jh source) that currently has no equivalent in lldbinit.)

How to debug with PureScript?

Issue
Following is a minimal, contrived example:
read :: FilePath -> Aff String
read f = do
log ("File: " <> f) -- (1)
readTextFile UTF8 f -- (2)
I would like to do some debug logging in (1), before a potential error on (2) occurs. Executing following code in Spago REPL works for success cases so far:
$ spago repl
> launchAff_ $ read "test/data/tree/root.txt"
File: test/data/tree/root.txt
unit
Problem: If there is an error with (2) - file is directory here - , (1) seems to be not executed at all:
$ spago repl
> launchAff_ $ read "test/data/tree"
~/purescript-book/exercises/chapter9/.psci_modules/node_modules/Effect.Aff/foreign.js:532
throw util.fromLeft(step);
^
[Error: EISDIR: illegal operation on a directory, read] {
errno: -21,
code: 'EISDIR',
syscall: 'read'
}
The original problem is more complex including several layers of recursions (see E-Book exercise 3), where I need logging to debug above error.
Questions
How can I properly log regardless upcoming errors here?
(Optional) Is there a more sophisticated, well-established debugging alternative - purescript-debugger? A decicated VS Code debug extension/functionality would be the cherry on the cake.
First of all, the symptoms you observe do not mean that the first line doesn't execute. It does always execute, you're just not seeing output from it due to how console works in the PureScript REPL. The output gets swallowed. Not the only problem with REPL, sadly.
You can verify that the first line is always executed by replacing log with throwError and observing that the error always gets thrown. Or, alternatively, you can make the first line modify a mutable cell instead of writing to the console, and then examine the cell's contents.
Finally, this only happens in REPL. If you put that launchAff_ call inside main and run the program, you will always get the console output.
Now to the actual question at hand: how to debug trace.
Logging to console is fine if you can afford it, but there is a more elegant way: Debug.trace.
This function has a hidden effect - i.e. its type says it's pure, but it really produces an effect when called. This little lie lets you use trace in a pure setting and thus debug pure code. No need for Effect! This is ok as long as used for debugging only, but don't put it in production code.
The way it works is that it takes two parameters: the first one gets printed to console and the second one is a function to be called after printing, and the result of the whole thing is whatever that function returns. For example:
calculateSomething :: Int -> Int -> Int
calculateSomething x y =
trace ("x = " <> show x) \_ ->
x + y
main :: Effect Unit
main =
log $ show $ calculateSomething 37 5
> npx spago run
'x = 37'
42
The first parameter can be anything at all, not just a string. This lets you easily print a lot of stuff:
calculateSomething :: Int -> Int -> Int
calculateSomething x y =
trace { x, y } \_ ->
x + y
> npx spago run
{ x: 37, y: 5 }
42
Or, applying this to your code:
read :: FilePath -> Aff String
read f = trace ("File: " <> f) \_ -> do
readTextFile UTF8 f
But here's a subtle detail: this tracing happens as soon as you call read, even if the resulting Aff will never be actually executed. If you need tracing to happen on effectful execution, you'll need to make the trace call part of the action, and be careful not to make it the very first action in the sequence:
read :: FilePath -> Aff String
read f = do
pure unit
trace ("File: " <> f) \_ -> pure unit
readTextFile UTF8 f
It is, of course, a bit inconvenient to do this every time you need to trace in an effectful context, so there is a special function that does it for you - it's called traceM:
read :: FilePath -> Aff String
read f = do
traceM ("File: " <> f)
readTextFile UTF8 f
If you look at its source code, you'll see that it does exactly what I did in the example above.
The sad part is that trace won't help you in REPL when an exception happens, because it's still printing to console, so it'll still get swallowed for the same reasons.
But even when it doesn't get swallowed, the output is a bit garbled, because trace actually outputs in color (to help you make it out among other output), and PureScript REPL has a complicated relationship with color:
> calculateSomething 37 5
←[32m'x = 37'←[39m
42
In addition to Fyodor Soikin's great answer, I found a variant using VS Code debug view.
1.) Make sure to build with sourcemaps:
spago build --purs-args "-g sourcemaps"
2.) Add debug configuration to VS Code launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "Launch Program",
"skipFiles": ["<node_internals>/**"],
"runtimeArgs": ["-e", "require('./output/Main/index.js').main()"],
"smartStep": true // skips files without (valid) source map
}
]
}
Replace "./output/Main/index.js" / .main() with the compiled .js file / function to be debugged.
3.) Set break points and step through the .purs file via sourcemap support.

lldb swift not printing debug variables

Swift LLDB in Xcode 6.4 is not printing values of any local variables inside my framework.
Here's what I have discovered so far.
(lldb) frame variable --no-args
cell = <Unable to determine byte size.>
(lldb) register read pc // get the current program counter value
rip = 0x00000001072177cf
(lldb) image lookup -va 0x00000001072177cf
Variable: id = {0x000a93a7}, name = "cell", type= "<NULL>", location = DW_OP_fbreg(-64), decl = CustomCollectionViewCell.swift:321
It seems like it's not able to find the type.
(lldb) image lookup -t CustomCollectionViewCell
(lldb)
I can see the image containing the type is loaded.
(lldb) image list
...
/path/to/CustomFramework
Moreover this file also contains the symbol.
$strings /path/to/CustomFramework | grep CustomCollectionViewCell
_TtC17CustomFramework24CustomCollectionViewCell
I do seem to have debug symbols since:
(lldb) script lldb.target.module['/data/Containers/Bundle/Application/23A3AF01-4F87-439F-B2F7-36E7BD09390B/MyApp.app/Frameworks/CustomFramework.framework/CustomFramework'].GetNumCompileUnits()
74
In addition the object file of the compiled swift file has the variable and type.
$ dwarfdump /path/to/FileUsingCell.o
0x00003140: TAG_variable [44]
AT_location( fbreg -8 )
AT_name( "cell" )
AT_decl_file( "CustomCollectionViewCell.swift" )
AT_decl_line( 324 )
AT_type( {0x0000133d} ( CustomCollectionViewCell ) )
Still I am not able to lookup the type.
I have checked that no striping is happening in the copy phase, and the release is debug.
Any ideas? I'd appreciate any help.

lldb - error: invalid thread #i

I am trying to perform some debugging using LLDB on a buggy code:
#IBAction func somePrettyAction(sender: AnyObject) {
let names = ["LLDB", "is", "fun", "Kudos :)"]
println("out of index name: \(names[5])")
}
So when app crashed at println (for obvious reasons ;)), I typed -'Thread Info' at XCode debugger console, and it gave me below output:
thread #1: tid = 0x6fbc, 0x000000010ee5f1d0 libswiftCore.dylib`Swift._fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt) -> () + 160, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
but when I typed - 't i', it showed below message:
error: invalid thread #i.
As per related wwdc video short form of given command should work, but for some reasons it is not working, any ideas?
Yeah, I noticed that too. The presentation is incorrect. That's not the abbreviation for thread info. A suitable abbreviation now is th i.
Using t is the abbreviation for thread select. Thus, t 2 is equivalent to thread select 2.
Type help at the (lldb) prompt, and it will show you a list of the current abbreviations.

Update value according to build type in Gradle

I am using Android Studio with Gradle build.
In my build.gradle, I want a variable's value to be different for different build type:
ext {
//By default, the value of myVar is 'debug'
myVar = 'debug'
}
android {
buildTypes {
release {
//update value of myVar to 'release'
project.ext.set("myVar","release")
}
debug {
//update value of myVar to 'debug'
project.ext.set("myVar","debug")
}
}
}
//I defined a task to check the value of myVar
task checkVar () {
println "My var is $myVar"
}
check.dependsOn(checkVar)
When I run command gradle clean assembleRelease , I expected to see a print out text My var is release. But, I see My var is debug . Why the value of myVar is not changed to release ?
What I want to achieve is to get the current build type during execution. Is there a better way to achieve this?
This won't work as it is a project scoped variable. the build type blocks are just configuration, so what really happens here (a bit simplified though):
You declare a variable named 'myVar' with a default value 'debug' assigned
You run the release configuration block and set the value of 'myVar' to 'release'
You run the debug configuration block and set the value of 'myVar' back to 'debug'
when executing the 'checkVar' task, the last assigned value is printed.
FYI: you can simplify 2. and 3. by just calling project.myVar = 'whatever'

Resources