Xcode 12.5 - cannot find '$__lldb_injected_self' in scope

I'm currently investigating a lldb regression on Xcode 12.5. The actual code involves complicated Swift logics: many levels of generic, protocols, extensions, etc, so I haven't figured out how to reproduce in a small sample code.

Here is what happens. po self (or po other local variables) doesn't work at certain breakpoints using Xcode 12.5. Below is the error message. For the same breakpoints, Xcode 12.4 works just fine.

(lldb) po self
error: warning: <EXPR>:11:7: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it
  var $__lldb_error_result = __lldb_tmp_error
  ~~~~^~~~~~~~~~~~~~~~~~~~
  _

error: <EXPR>:19:5: error: cannot find '$__lldb_injected_self' in scope
    $__lldb_injected_self.$__lldb_wrapped_expr_6(
    ^~~~~~~~~~~~~~~~~~~~~

If I understand correctly, when evaluating an expression, lldb generates some code and compile it. The above error happens on compiling the generated code.

extension $__lldb_context {
  @LLDBDebuggerFunction @available(iOS 14.5, *)
  final func $__lldb_wrapped_expr_6(_ $__lldb_arg : UnsafeMutablePointer<Any>) {

    do {
    /*__LLDB_USER_START__*/
    self
    /*__LLDB_USER_END__*/
    } catch (let __lldb_tmp_error) {
      var $__lldb_error_result = __lldb_tmp_error
   }
  }
}
@available(iOS 14.5, *)
func $__lldb_expr(_ $__lldb_arg : UnsafeMutablePointer<Any>) {
  do {
    $__lldb_injected_self.$__lldb_wrapped_expr_6(
      $__lldb_arg
    )
  }
}

I compared the lldb log (log enable lldb expr) between a working breakpoint and a broken one, and found that, at the working breakpoint, lldb inserted __lldb_injected_self while for the broken breakpoint it didn't. This explains why the error "cannot find '$__lldb_injected_self' in scope" because it's not inserted.

[SwiftASTManipulator::AddExternalVariables] Injected variable (var_decl implicit range=[<EXPR>:17:62 - line:17:62] "$__lldb_injected_self" type='SomeType<SomeGenericType>' interface type='SomeType<SomeGenericType>' access=public readImpl=stored writeImpl=stored readWriteImpl=stored)

I also noticed some weirdness of the frame: self=<unavailable> and self = <Unable to determine byte size. It may be worh mentioning we have -Onone set.

(lldb) frame info
frame #0: 0x0000000113be3cd8 ExploreSectionPlugins`ExploreValuePropsSectionPluginV3.itemModels(section=$s23ExploreModelsFoundation0A20SearchResultsSectionVy0aF7Plugins0a10ValuePropsF8FragmentVGD @ 0x00007ffee082e8c8, context=0x0000000000000000, self=<unavailable>) at ExploreValuePropsSectionPluginV3.swift:47:5
(lldb) frame variable self
(ExploreSectionPlugins.ExploreValuePropsSectionPluginV3<Dependencies>) self = <Unable to determine byte size.>

After following along the lldb source code, it looks here is where the __lldb_injected_self should be inserted, but I hit a wall there and didn't know what to do next.

How can I gather more information about this? I hope to figure out a sample code to repro the issue and potentially file a bug report. Any tips, suggestions and advices are appreciated!

5 Likes

What you are seeing here are the symptoms of LLDB not being able to determine the type of self. The self=<unavailable> and self = <Unable to determine byte size are the real underlying problems. We should also improve the error message in the expression evaluator to be more helpful. What's the type of self? When you are trying to create a small reproducer, replicating the kind of type that self has will be the most important ingredient.

3 Likes

Thanks, @Adrian_Prantl. I'm finally able to figure out a sample code to repro this problem and filed a ticket here. It turns out to be related to generic types and -disable-reflection-metadata compiler flag.

Thanks for the report! Generally speaking, If you -disable-reflection-metadata you will effectively break LLDB. LLDB heavily relies on reflection metadata for type information.

1 Like

What's your motivation for disabling reflection metadata? In theory, one imagine a workflow where dsymutil collects reflection metadata so it could be stripped out. But I'd like to learn more about why people feel the need to strip reflection metadata to gauge whether such a feature makes sense.

LLDB heavily relies on reflection metadata for type information.

This is good to know. Can -disable-reflection-names also break LLDB?

What's your motivation for disabling reflection metadata?

The app size is the primary concern here. We just measured it again. By disabling the reflection metadata, the binary size can be reduced by ~7.5MB(~3.6%). If the reflection metadata can be stripped out, this will be less a concern, but it doesn't seem to be case now.

1 Like

This is good to know. Can -disable-reflection-names also break LLDB?

I'm not sure what exactly that option controls so you'd have to experiment a bit.

but it doesn't seem to be case now.

Strip doesn't know about reflection metadata at this point, this is just a potential workflow that we could support in the future if there is enough interest for it to justify it.

1 Like

I have the same issue on Xcode 14 beta when passing Any? type parameter

error: expression failed to parse:
warning: <EXPR>:11:7: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it
  var $__lldb_error_result = __lldb_tmp_error
  ~~~~^~~~~~~~~~~~~~~~~~~~
  _

error: <EXPR>:19:5: error: cannot find '$__lldb_injected_self' in scope
    $__lldb_injected_self.$__lldb_wrapped_expr_52(
    ^~~~~~~~~~~~~~~~~~~~~

the v command works as expected (but this command depends in reflection/debug info so its a different command)

@Mike do you have a small reproducer? If you can't reproduce in a small example could you share the types involved?

@augusto2112
Sorry, I complained before checking myself (the error may be a little misleading in my case)
calling a swift class method (in extension) from Objc and try to po self (it dosent make sense to have self in class method, I think maybe a different error could make it more clear)

Sorry, still not totally clear what the situation is. You're stopped in a Swift class method that's declared in an extension of an Obj-C type? And what are you doing po on? A parameter to the class function of type Any?

I am stoping in extension of swift class method (that is called from Objc) and doing a po on self (which does not make sense )