How do i read references given by ptr_refs in iOS?

可紊 提交于 2020-07-19 10:58:08

问题


When printing list of references with ptr_refs, it gives somewhat vague results (at least in iOS). For example I have a sample app with this tiny ViewController class and exactly one outlet reference to a UILabel instance:

import UIKit

class ViewController: UIViewController {

    @IBOutlet var label: UILabel!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print(label)
    }

}

And here is the listing I get when printing references to the label:

(lldb) ptr_refs 0x102914810
0x0000000281b04630: malloc(    16) -> 0x281b04630
0x0000000283d09f18: malloc(    96) -> 0x283d09ec0 + 88    
0x0000000280c18d60: malloc(    64) -> 0x280c18d40 + 32     CFXNotificationNameWildcardObjectRegistration0 bytes after CFXNotificationNameWildcardObjectRegistration
0x000000028192b408: malloc(    32) -> 0x28192b400 + 8      _UILabelStringContent._UILabelContent._defaultAttributesProvider
0x0000000283a3d2f0: malloc(    80) -> 0x283a3d2c0 + 48     CFXNotificationObjcObserverRegistration8 bytes after CFXNotificationObjcObserverRegistration
0x0000000283a3d2f8: malloc(    80) -> 0x283a3d2c0 + 56     CFXNotificationObjcObserverRegistration16 bytes after CFXNotificationObjcObserverRegistration
0x000000010290c070: malloc(   864) -> 0x10290bd20 + 848    TtC13ThreadChecker14ViewController216 bytes after TtC13ThreadChecker14ViewController
0x0000000102d058c0: malloc(   304) -> 0x102d05850 + 112

If this was not just a sample app and it had rather 10-15 outlet references, I would have a hard time trying to figure out which exact reference in my code this line is at - 0x000000010290c070: malloc( 864) -> 0x10290bd20 + 848 TtC13ThreadChecker14ViewController216 bytes after TtC13ThreadChecker14ViewControllerThe.

I also tried the -s option with MallocStackLogging enabled, but when it comes to outlet references, this information is not very helpful.

Provided I have only the address of an object and the listing given by ptr_refs, is there a way to find out which exact variable/field in my code corresponds to the reference in the listing?


回答1:


Firstly, the names on the right give us some clues, from which you could guess that TtC13ThreadChecker14ViewController is associated with your ViewController class.

_Tt is for target; C is for class; 13 is the length of the "ThreadChecker" string, and your project name is ThreadChecker; 14 is the length of the "ViewController" string, and that is the class. Your ViewController starts at 0x10290bd20.

Secondly, the malloc is at 0x000000010290c070. Notice that 0x000000010290c070 - 0x10290bd20 = 0x350 which is 848 in decimal, so that's why it puts the offset as 848 from the start of "ViewController", i.e., 0x10290bd20 + 848. So this offset, 848, is an important piece of the puzzle.

Thirdly, the next thing to do is figure out what line in the source code is at offset 848. For this, we begin by doing

(lldb) image list
[  0] 4EB96CD6-42E0-34D8-AB5B-2418F5C55678 0x000000010252c000 /Users/daniel.wong/Library/Developer/Xcode/DerivedData/testLLDB-eqmuowhdphumqdhcyvcydgrybiue/Build/Products/Debug-iphonesimulator/testLLDB.app/testLLDB 

Even in this simple example, there might be 200-300 libraries loaded with the app. For the present investigation of your own source code, you can ignore the libraries, only look at the [ 0] (first element in the list). (in my example, the app is called testLLDB; in yours, you might see ThreadChecker instead of testLLDB).

An important point to note is that image list gives the so-called file address where the addresses you got from Xcode that you used for ptr_refs might be quite different (actual addresses in the simulator or iPhone memory during an actual run when it gets loaded into a part of the RAM), e.g., 0x102914810 in your example. The file address refers to a virtual address as defined by each object file. For the purpose of finding the source code line number with the offset 848, you can work with these file addresses and you now just need one more piece of information, i.e., where is the start of the code for ViewController, so you can take offset 848 from there.

Fourthly, to find the start of the code for ViewController, you can use

(lldb) image dump sections  /Users/daniel.wong/Library/Developer/Xcode/DerivedData/testLLDB-eqmuowhdphumqdhcyvcydgrybiue/Build/Products/Debug-iphonesimulator/testLLDB.app/testLLDB

where we specified only the image of the testLLDB app that we got as the first element of the image list, and not the 100s of libraries after that.

lldb will then give you something like:

Sections for '/Users/daniel.wong/Library/Developer/Xcode/DerivedData/testLLDB-eqmuowhdphumqdhcyvcydgrybiue/Build/Products/Debug-iphonesimulator/testLLDB.app/testLLDB' (x86_64):
  SectID     Type             Load Address                             Perm File Off.  File Size  Flags      Section Name
  ---------- ---------------- ---------------------------------------  ---- ---------- ---------- ---------- ----------------------------
  0x00000100 container        [0x0000000000000000-0x0000000100000000)* ---  0x00000000 0x00000000 0x00000000 testLLDB.__PAGEZERO
  0x00000200 container        [0x000000010252c000-0x0000000102532000)  r-x  0x00000000 0x00006000 0x00000000 testLLDB.__TEXT
  0x00000001 code             [0x000000010252d260-0x000000010252fa80)  r-x  0x00001260 0x00002820 0x80000400 testLLDB.__TEXT.__text
  0x00000002 code             [0x000000010252fa80-0x000000010252fb5e)  r-x  0x00003a80 0x000000de 0x80000408 testLLDB.__TEXT.__stubs
  0x00000003 code             [0x000000010252fb60-0x000000010252fce2)  r-x  0x00003b60 0x00000182 0x80000400 testLLDB.__TEXT.__stub_helper
  0x00000004 data-cstr        [0x000000010252fce2-0x00000001025309bf)  r-x  0x00003ce2 0x00000cdd 0x00000002 testLLDB.__TEXT.__objc_methname
  0x00000005 data-cstr        [0x00000001025309c0-0x0000000102531817)  r-x  0x000049c0 0x00000e57 0x00000002 testLLDB.__TEXT.__cstring
  0x00000006 regular          [0x0000000102531820-0x0000000102531b50)  r-x  0x00005820 0x00000330 0x00000000 testLLDB.__TEXT.__const
...

There's more, but for this simple ViewController, these first few sections are enough for our purpose. Look at the first code section, where its range is [0x000000010252d260-0x000000010252fa80). So it is starting from 0x000000010252d260. Here is where we add the offset 848. But we add in hex, so we add 0x350 to 0x000000010252d260 to get 0x000000010252d5b0.

Fifthly and finally, we can see which part of our source code was referencing the label, by:

(lldb) image lookup -a 0x000000010252d5b0 --verbose
  Address: testLLDB[0x00000001000015b0] (testLLDB.__TEXT.__text + 848)
  Summary: testLLDB`key path getter for testLLDB.ViewController.label : Swift.Optional<__C.UILabel> : testLLDB.ViewController + 80 at <compiler-generated>
   Module: file = "/Users/daniel.wong/Library/Developer/Xcode/DerivedData/testLLDB-eqmuowhdphumqdhcyvcydgrybiue/Build/Products/Debug-iphonesimulator/testLLDB.app/testLLDB", arch = "x86_64"
  CompileUnit: id = {0x00000000}, file = "/Users/daniel.wong/OneDrive - V-Key Pte Ltd/ios/testLLDB/testLLDB/testLLDB/ViewController.swift", language = "swift"
 Function: id = {0x10000032e}, name = "key path getter for testLLDB.ViewController.label : Swift.Optional<__C.UILabel> : testLLDB.ViewController", mangled = "$s8testLLDB14ViewControllerC5labelSo7UILabelCSgvpACTK", range = [0x000000010252d560-0x000000010252d5bf)
 FuncType: id = {0x10000032e}, byte-size = 8, compiler_type = "() -> ()
"
   Blocks: id = {0x10000032e}, range = [0x10252d560-0x10252d5bf)
LineEntry: [0x000000010252d560-0x000000010252d5c0): /Users/daniel.wong/OneDrive - V-Key Pte Ltd/ios/testLLDB/testLLDB/<compiler-generated>
   Symbol: id = {0x000000a4}, range = [0x000000010252d560-0x000000010252d5c0), name="key path getter for testLLDB.ViewController.label : Swift.Optional<__C.UILabel> : testLLDB.ViewController", mangled="$s8testLLDB14ViewControllerC5labelSo7UILabelCSgvpACTK"
 Variable: id = {0x100000345}, name = "label", type = "testLLDB.ViewController", location = DW_OP_fbreg(-16), decl = ViewController.swift:18

So we see it is "key path getter for testLLDB.ViewController.label : Swift.Optional<__C.UILabel> : testLLDB.ViewController" at ViewController.swift:18, which is what you were looking for. (ok, for my test view controller, the label is in line 18, as I also had a viewDidLoad that took a few lines; for yours, you should get the appropriate line number for your ViewController).

This post is already too long, but just to add one more little piece of info: those references to your label from CFXNotificationObjcObserverRegistration, that is part of CoreFoundation, so we see that not at references are from our own source code. Many references would often be from system frameworks like CoreFoundation, etc.; if you put your view with the label in a storyboard and add auto layout constraints, for example, the ptr_refs command will additionally give you a number of other references that are related to auto layout, e.g.,

NSContentSizeLayoutConstraint.NSLayoutConstraint._container
0x000060000049ce48: malloc(    96) -> 0x60000049ce40 + 8      NSContentSizeLayoutConstraint.NSLayoutConstraint._container
0x00006000035db208: malloc(    64) -> 0x6000035db200 + 8      NSLayoutDimension.NSLayoutAnchor._referenceItem
0x00006000035db3c8: malloc(    64) -> 0x6000035db3c0 + 8      NSLayoutDimension.NSLayoutAnchor._referenceItem
0x00006000035e9560: malloc(    64) -> 0x6000035e9540 + 32 


来源:https://stackoverflow.com/questions/62310636/how-do-i-read-references-given-by-ptr-refs-in-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!