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.
Related
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.)
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.
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.
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.
I am trying to generate a dynamic assembly using Reflection & Emit in .NET. I am getting an error, "Common Language Runtime detected an invalid program." I created another program which has the functionality I want using hard-coded types. The functionality I am trying to write will ultimately use dynamic types, but I can use ILDasm to see the IL I need to generate. I am comparing the IL I am generating with the IL which the compiler generates. In the .locals init declaration of one method I see there is an extra item in the compiler-generated code,
compiler-generated:
.locals init ([0] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
[1] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0001)
mine:
.locals init (class [System.Core]System.Linq.Expressions.ParameterExpression V_0,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_1)
I don't understand the significance of the "[0]" and "[1]" in the compiler-generated code. Can anyone tell me what it means?
As a more general question, I can follow most ILDasm output without too much trouble. But every so often I run across a problematic expression. For instance, in this line from ILDasm
callvirt instance class [EntityFramework]System.Data.Entity.ModelConfiguration.EntityTypeConfiguration`1<!!0> [EntityFramework]System.Data.Entity.DbModelBuilder::Entity<class DynamicEdmxTrial.HardFooAsset>()
the "!!0" probably refers to the generic type of the Entity<>, but I don't know for sure, and I wonder if there is a key to ILDasm output that would explain its more obscure output to me.
The specification is freely available here. It takes a little getting used to, but most details are easily found once you figure out the structure.
!! is listed in II.7.1 Types:
Type ::= | Description | Clause
‘!’ Int32 | Generic parameter in a type definition, | §II.9.1
| accessed by index from 0 |
| ‘!!’ Int32 | Generic parameter in a method | §II.9.2
| definition, accessed by index from 0 |
...
In other words, inside a method that C# would call f<T, U>(), !!0 would be T, and !!1 would be U.
However, the [0] is a good question. The spec does not seem to address it. The .locals directive is described in II.15.4.1.3 The .locals directive, which lists the syntax as
MethodBodyItem ::= ...
| .locals [ init ] ‘(’ LocalsSignature ‘)’
LocalsSignature ::= Local [ ‘,’ Local ]*
Local ::= Type [ Id ]
There is nothing that seems to allow [0] there unless it is part of a Type, and Type does not allow anything starting with [ either. My guess is that this is an undocumented peculiarity specific to Microsoft's implementation, intended to help the human reader see that location 0 is local variable CS$0$0000, for when the generated instructions access local variables by index.
Experimenting with ILAsm shows that this is exactly what it means. Taking a simple C# program:
static class Program {
static void Main() {
int i = 0, j = 1;
}
}
and compiling and then disassembling it (csc test.cs && ildasm /text test.exe >test.il) shows:
....
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ldc.i4.1
IL_0004: stloc.1
IL_0005: ret
....
Modifying the .locals to
.locals init ([0] int32 V_0, [0] int32 V_1)
gives a useful warning message:
test.il(41) : warning : Local var slot 0 is in use
And indeed, declaring variables of different types, then reordering them using [2], [1], [0], assembling and immediately disassembling the result, shows that the variables got reordered.