Chapter 7: Image - What is the difference between these 2 commands

Hi

Thanks @lolgrep for this great book!

My question is related to “chapter 7: Image” about inspecting the block object’s members.
I found out that you mentioned 2 ways for this, either by:

  1. querying for the object knowing the type by using the image command, e.x:
    (lldb) image lookup -t __block_literal_5
  2. querying the object knowing the type and the memory address, and dereferencing it, using the p command, e.x:
    (lldb) p *(__block_literal_5 *)0x0000618000070200

Both are dumping kinda similar info, but I can’t exactly put my fingers on the exact difference between them.

So my questions are:
1) What exactly are the differences between the 2 ways mentioned above.
2) Why I can’t use image lookup -a 0x0000618000070200 to print the object details as the help image lookup states?
3) When I execute image lookup -t __block_literal_5, it dumps:

id = {0x100000c70}, name = "__block_literal_5" // and some more info too

what is the id? Shouldn’t it be the memory address of the __block_literal_5?

4) In section “Snooping around” of chapter 7, you mentioned that I have to increment the retainCount by using the -[__NSMallocBlock retain], otherwise the block will disappear when the references that are retaining this block release their control. So I tried to -[NSBlock invoke] and when I call -[__NSMallocBlock retainCount], it’s always 1. Is there any explanation for this? Why it never disappears?

Notes:

  1. 0x0000618000070200 is the address of the __block_literal_5
  2. I’m reading from the book v.3.0.
1 Like

@lolgrep Can you please help with this when you get a chance? Thank you - much appreciated! :]

1). The image lookup -t __block_literal_5 method is consulting LLDB’s type system (which in turn is consulting the DWARF debugging info). When LLDB attaches to a process is has to go thread each and every module that’s loaded and parse any known data structures in the module’s symbol table (symbol tables are discussed a bit in the Mach-O chapters) and debugging info, if available.

The p *(__block_literal_5 *)0x0000618000070200 method is casting that address to the __block_literal_5 type, which is giving you the real life values of that block instance.

Another way of phrasing this is, one method is examining the members of a struct, the other is examining an instance of that struct.

Also check out these slides from a presentation on Objective-C block layout Reverse Engineering the iOS Simulator's SpringBoard - Speaker Deck

You can find the implementation of Objective-C blocks here: Block_private.h

2). That address 0x0000618000070200 is an instance of the __block_literal_5 struct which is created on the heap (although not all Objective-C blocks are all created on the heap, some can be created on the stack). LLDB is not smart enough to figure this out since it’s an address that is created at runtime. That being said, it’s definitely possible to do some address sleuthing to try and determine what this address is via a custom LLDB script.

3). The id should not be interesting to you. It is used by the DWARF debugging to associate pointers to the correct types. When you pause in Xcode on a certain function, that function is consulting the debugging information provided by the compiler on the objects in that function as well as their types to give you information about what those references contain. DWARF debugging is a complex topic, there’s not really any need for you to know the details unless you are implementing your own parser for this information.

4). Looks like you found an error in the book. When I originally wrote that chapter, the block logic was a bit different. Now it looks like the retainCount is hardcoded to 1

Looking at the assembly…

CoreFoundation`-[__NSMallocBlock retainCount]:
->  0x109517ed0 <+0>:  push   rbp
    0x109517ed1 <+1>:  mov    rbp, rsp
    0x109517ed4 <+4>:  mov    eax, 0x1
    0x109517ed9 <+9>:  pop    rbp
    0x109517eda <+10>: ret    
    0x109517edb <+11>: nop    dword ptr [rax + rax]

Notes:

  1. 0x0000618000070200 is the instance of __block_literal_5, not the address of __block_literal_5
  2. Awesome :]
1 Like

This topic was automatically closed after 166 days. New replies are no longer allowed.