Redirect lldb output to file
Asked Answered
U

5

19

I'm using lldb inside Xcode, and one of my variables contains a huge chunk of JSON data. Using po myVar isn't much helpful to analyse this data, as it will output in the tiny Xcode debug console.

Is there a way to redirect lldb output to a file ?

I saw here that such a feature seems to be available on gdb as :

(gdb) set logging on
(gdb) set logging file /tmp/mem.txt
(gdb) x/512bx 0xbffff3c0
(gdb) set logging off

and is "translated" in lldb as :

(lldb) memory read --outfile /tmp/mem.txt --count 512 0xbffff3c0
(lldb) me r -o/tmp/mem.txt -c512 0xbffff3c0
(lldb) x/512bx -o/tmp/mem.txt 0xbffff3c0

However, the memory read command will not help in my case, and apparently, --outfile is not available for the print command.

Ursola answered 4/10, 2013 at 8:29 Comment(0)
S
18

You can use a Python script to do so (and much more), as explained here:

LLDB Python scripting in Xcode

Create a file named po.py in a directory of your choice (for example "~/.lldb"):

import lldb

def print_to_file(debugger, command, result, dict):
  #Change the output file to a path/name of your choice
  f=open("/Users/user/temp.txt","w")
  debugger.SetOutputFileHandle(f,True);
  #Change command to the command you want the output of
  command = "po self"
  debugger.HandleCommand(command)

def __lldb_init_module (debugger, dict):
  debugger.HandleCommand('command script add -f po.print_to_file print_to_file ')

Then in lldb write:

command script import ~/.lldb/po.py
print_to_file
Sandstone answered 12/10, 2013 at 8:24 Comment(5)
Improvements here: why not make the command an argument - then you could say “print_to_file po self”? Also, I haven’t checked whether LLDB automagically resets the handles for you, but it would seem good practice to reset the output file handle :) Lastly, you could actually just fetch the SBCommandReturnObject for the ‘inferior command’ (po self in the example) and write it to a file instead of hijacking lldb’s stdout. I would generally be wary of trying to play around with stdin/stdout if at all avoidable.Lomasi
Is there a way to redirect all debugger output to a file? I tried the above script without HandleCommand line and it didn't work.Joerg
Enrico, could you consider showing an example/answer of your own that improves upon this one? I like the sound of your approach but I don't have enough info to test it.Cenesthesia
For very large structures, the data seems to get truncated to about 61000 lines, 1.4M... Not sure if im missing a cache setting somewhereFahland
Note that this pipes all further output from any command to the file, unless you get the original handle w/ debugger.GetOutputFileHandle() and restore it after the handler executes.Atman
F
5

I found session save <filename> to be a much better, easier option than those listed here. It's not quite the same as you can't use it (to my knowledge selectively) but for generating logs, it's quite handy.

Flasher answered 27/9, 2022 at 19:23 Comment(0)
N
4

Redirect lldb command output to file

two method:

  • session save
  • lldb python script add new command (eg: write)

session save

  • syntax: session save {outputFileFullPath}
    • Pros: no need extra command, save all session output to file
    • Cons: can not save specific command output to single file
  • example:
    • session save /Users/crifan/dev/tmp/sub_1000A0460.txt
      • lldb sub_1000A0460.txt

lldb script add new command: write

refer: 4iar/lldb-write: Write the output of an lldb command to file

steps:

  • download code
    • git clone https://github.com/4iar/lldb-write.git
  • add to lldb init script
    • vi ~/.lldbinit
    • add command script import /{change_to_your_path}/lldb-write/write.py
  • restart lldb
  • usage
    • write /some/path/outputFile.txt {yourOriginLldbCommand}
  • example
    • for dis -f is: write /Users/crifan/dev/tmp/lldb_akd_symbol2575_disassemble.txt dis -f
      • lldb_akd_symbol2575_disassemble
Nightingale answered 6/5, 2023 at 4:5 Comment(0)
S
1

Here is a slight modification incorporating some of the comments from above:

def toFile(debugger, command, result, dict):
    f=open("/Users/user/temp.txt","w")
    debugger.SetOutputFileHandle(f,True);
    debugger.HandleCommand(command)  
    f.close()
    debugger.SetOutputFileHandle(sys.stdout, True)

This allows the command to be supplied as an argument, and reverts the output file handle to stdout after the command is run.

Saville answered 10/6, 2015 at 15:57 Comment(2)
Did you try it? I get: ValueError: file descriptor cannot be a negative integer (-1)Airglow
I figured it out. You have to use debugger.SetOutputFileHandle(sys.__stdout__, True)Airglow
M
1

Assuming that you have a variable named jsonData (which has a Data type) you can save it to a file with this command:

expr jsonData.write(to: URL(fileURLWithPath: "/tmp/datadump.bin"))

Alternatively instead of above command you could dump memory used by this variable to a file as in the example below:

(lldb) po jsonData
▿ Optional<Data>
  ▿ some : 32547 bytes
    - count : 32547
    ▿ pointer : 0x00007fe8b69bb410
      - pointerValue : 140637472797712

(lldb) memory read --force --binary --outfile /tmp/datadump.bin --count 32547 0x00007fe8b69bb410
32547 bytes written to '/tmp/datadump.bin'
Moten answered 4/10, 2021 at 14:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.