<div dir="ltr">Thanks for the info. I will use a solution similar to that. <div><br></div><div>Jeffrey</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 8, 2016 at 10:41 AM, Greg Clayton <span dir="ltr"><<a href="mailto:gclayton@apple.com" target="_blank">gclayton@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
> On Mar 7, 2016, at 5:27 PM, Jeffrey Tan <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>> wrote:<br>
><br>
> Thanks for the info, I will debug this.<br>
> One more quick question related to this: in full path breakpoint case(IDE scenario), do we compare both file name and directory path exact match and bind breakpoint successfully? I ask this because of the breakpoint issue I found:<br>
> 1. I have a symbolic link folder "/home/jeffreytan/foo/" which points to "/data/users/jeffreytan/bar/foo".<br>
> 2. If I built cpp file in /home/jeffreytan/foo/, and try to set breakpoint using real path "b /data/users/jeffreytan/bar/foo/main.cpp:10" it will fail to bind.<br>
> 3. While "b /home/jeffreytan/foo//main.cpp:10" binds fine, vise verse.<br>
<br>
</span>Yep, that will fail for the reason that "/home/jeffreytan/foo" won't match "/data/users/jeffreytan/bar/foo" and we don't resolve paths on debug info because of the cost as we mentioned before.<br>
<span class=""><br>
><br>
> I can't control how users open/build file in our IDE, they may choose to open/build from symbolic link folder or real path folder. What is the general suggestion to deal with symbolic link differences?<br>
<br>
</span>There isn't a good one right now. One idea is to try and track the project directory in your IDE, like "/home/jeffreytan/foo", and note that this is the base directory. Then have the IDE always set the breakpoint by basename ("main.cpp") and then filter the results out based on where the file is in the project directory. So if you have your main file in your project directory as "src/main.cpp", you would set a breakpoint in main.cpp, and then look at the locations that the breakpoint had and disable any locations that don't have a matching parent directory of "src"...<br>
<span class="HOEnZb"><font color="#888888"><br>
Greg<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
><br>
> Jeffrey<br>
><br>
><br>
><br>
><br>
> On Mon, Mar 7, 2016 at 4:25 PM, Greg Clayton <<a href="mailto:gclayton@apple.com">gclayton@apple.com</a>> wrote:<br>
><br>
> > On Mar 7, 2016, at 4:08 PM, Jeffrey Tan <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>> wrote:<br>
> ><br>
> > Hi Greg,<br>
> ><br>
> > I am not sure if I understand the behavior here: the long relative file path from our build system does *not* exist on file system, do you mean lldb will always try to resolve this relative path to a *real* file on file system using stat() call?<br>
><br>
> No it doesn't do that and that is why you path remains as is.<br>
><br>
> > And it will fail to bind the breakpoint if can't find the resolved file path?<br>
><br>
> No it shouldn't if you set it by basename. If it does fail to set the breakpoint using "EATAnimatedView.m" as the filename, then it is a bug.<br>
><br>
> ><br>
> > Per my testing, I was able to use #1. "b EATAnimatedView.m:33" to bind breakpoint, but not:<br>
> > #2, "b .//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m:20"<br>
><br>
> That is interesting, and you will need to track down why this is happening. Obviously we are expecting this kind of path and something is going wrong.<br>
><br>
> > break list --verbose<br>
> > Current breakpoints:<br>
> > 2: file = './/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m', line = 20<br>
> ><br>
> > 3: file = 'EATAnimatedView.m', line = 33<br>
> >     3.1:<br>
> >       module = /Users/jeffreytan/Library/Developer/CoreSimulator/Devices/32967F60-A4C3-43DC-ACA8-92D819413362/data/Containers/Bundle/Application/96DA24F5-E35D-402F-B4B7-1C5BBD40B270/MPKEats.app/MPKEats<br>
> >       compile unit = EATAnimatedView.m<br>
> >       function = -[EATAnimatedView initWithFrame:imageNames:animationDuration:repeatCount:touchEnabled:]<br>
> >       location = ./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m:33<br>
> >       address = 0x000000010a1ff798<br>
> >       resolved = true<br>
> >       hit count = 0<br>
> ><br>
> > Do you mean #2 should work?<br>
><br>
> I would expect #2 to work, but not surprised it doesn't.<br>
><br>
> > I think I am a bit vague on how source breakpoint is supposed to work. What is the algorithm to successfully bind breakpoint here?<br>
><br>
> What we currently do is break all file paths up into a basename (EATAnimatedView.m) and a directory (.//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View).<br>
><br>
> We break up filenames like this because the user will rarely type full paths in commands. IDEs will often give us full paths to files, but users rarely do. So to efficiently store files and make them easy to compare, we split the path up into two strings. Each string gets constified by being placed into a ConstString object that uniques the string and gives out the same pointer for each string it uniques so we can use pointer comparisons to compare two strings. FileSpec objects contain:<br>
><br>
> class FileSpec<br>
> {<br>
> protected:<br>
>     //------------------------------------------------------------------<br>
>     // Member variables<br>
>     //------------------------------------------------------------------<br>
>     ConstString m_directory;    ///< The uniqued directory path<br>
>     ConstString m_filename;     ///< The uniqued filename path<br>
>     mutable bool m_is_resolved; ///< True if this path has been resolved.<br>
>     PathSyntax m_syntax;        ///< The syntax that this path uses (e.g. Windows / Posix)<br>
> };<br>
><br>
><br>
> So we can easily compare strings. You should probably step through some code and figure out why things are not matching up. The FileSpec class has some functions that try to clean up paths without calling stat:<br>
><br>
>     void<br>
>     FileSpec::NormalizePath ();<br>
><br>
>     void<br>
>     FileSpec::RemoveBackupDots (const ConstString &input_const_str, ConstString &result_const_str);<br>
><br>
> And a few others. They might be causing the problems. You will need to debug this if you wish to figure out what is going wrong.<br>
><br>
> A few tests that I ran include:<br>
><br>
> (lldb) script<br>
> Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.<br>
> >>> f = lldb.SBFileSpec('.//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m', False)<br>
> >>> print f.GetFilename()<br>
> EATAnimatedView.m<br>
> >>> print f.GetDirectory()<br>
> .//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View<br>
> >>> f = lldb.SBFileSpec('.//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m', True)<br>
> >>> print f.GetFilename()<br>
> EATAnimatedView.m<br>
> >>> print f.GetDirectory()                                                                                                                                                          .//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View<br>
><br>
><br>
> So we seem to split the path up correctly in both cases where we don't resolve and resolve the path.<br>
><br>
><br>
> ><br>
> > Jeffrey<br>
> ><br>
> ><br>
> ><br>
> > On Mon, Mar 7, 2016 at 11:07 AM, Greg Clayton <<a href="mailto:gclayton@apple.com">gclayton@apple.com</a>> wrote:<br>
> > Not sure why we aren't treating this as a relative path. Probably because of the 1000 '/' characters. Feel free to dig into lldb_private::FileSpec and play around and see where things are going wrong.<br>
> ><br>
> > You can probably fix LLDB, when it resolves paths, to clean this up, but we typically don't resolve paths that we find in debug info when we run into it. Why? Because if you have DWARF info that contains paths that map to 10000 files that exist on network file system mounts, we would need to resolve all of those paths as we parse the line tables and calling stat() on all these files take a TON of time. So we won't resolve paths we find in debug info typically. We could try and run a path resolving function that doesn't call stat() to fix up an really bad paths like the ones that your build system is making, but we don't have support for that right now due to the network file system stat() issue.<br>
> ><br>
> > Greg<br>
> ><br>
> > > On Mar 5, 2016, at 11:47 AM, Jeffrey Tan <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>> wrote:<br>
> > ><br>
> > > Ooops, I accidentally dropped lldb mail list.<br>
> > > I have chatted this long relative path issue with our buck build team, they seem to do some kind of post-processing for the symbol files but failed to run another scripts to resolve the processed paths back into absolute path. And they are unable to fix this in short time. :-(<br>
> > ><br>
> > > I am building a workaround for this issue:<br>
> > > I am building a middle indirection map between debugger UI and lldb. Whenever I enumerate a SBFileSpec a source line, I get the source file long relative path from it and add basepath of the build project then normalize into an absolute path, then store absolute_path->SBFileSpec mapping into the map, then send the absolute path to debugger UI. When the debugger UI is trying to set source line breakpoint, I got the absolute path back from debugger UI and use the middle indirection map to find corresponding SBFileSpec for that source file. Finally, I used the SBFileSpec to set source line breakpoint.<br>
> > > The assumption is that as long as I used the same SBFileSpec from lldb, I should use it to set source line breakpoint successfully.<br>
> > > However, it turns out this still does not work. The breakpoints are listed as pending:<br>
> > ><br>
> > > break list<br>
> > > Current breakpoints:<br>
> > > 1: file = './/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/App/main.m', line = 9, locations = 0 (pending)<br>
> > > 2: file = './/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m', line = 20, locations = 0 (pending)<br>
> > ><br>
> > > Questions:<br>
> > > Isn't lldb treating this long relative path as *absolute path* so as long as this long path is used to set breakpoint it should work? Any idea why this workaround approach does not work?<br>
> > ><br>
> > > Jeffrey<br>
> > ><br>
> > > On Wed, Jan 6, 2016 at 8:47 AM, Jeffrey Tan <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>> wrote:<br>
> > > Nevermind, I do not know why "GetSelectedTarget().BreakpointCreateByLocation("EATAnimatedView.m", line)" does not work for me last October. I tried it again, it works now.<br>
> > > I will see if I can figure out the weird relative location path in symbol file issue.<br>
> > ><br>
> > > Thanks!<br>
> > ><br>
> > > On Tue, Jan 5, 2016 at 3:38 PM, Jeffrey Tan <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>> wrote:<br>
> > > Sorry for the late response. I finally had time to come back to this issue.<br>
> > ><br>
> > > Can anyone help me with the "self.debugger.GetSelectedTarget().BreakpointCreateByLocation("EATAnimatedView.m", line)" not working issue? Does it suppose to work? I can reproduce it pretty easily in a small python script.<br>
> > ><br>
> > > I found the following lldb test that uses this API:<br>
> > > <a href="http://www.opensource.apple.com/source/lldb/lldb-69/test/lang/objc/objc-stepping/TestObjCStepping.py" rel="noreferrer" target="_blank">http://www.opensource.apple.com/source/lldb/lldb-69/test/lang/objc/objc-stepping/TestObjCStepping.py</a><br>
> > ><br>
> > > So it seems that this should work. Am I doing something wrong? I am importing the Xcode's lldb by following:<br>
> > > developer_dir = subprocess.check_output(['xcode-select', '--print-path'])<br>
> > >     lldb_pythonpath = os.path.join(<br>
> > >         developer_dir.strip(), '../SharedFrameworks/LLDB.framework/Resources/Python')<br>
> > >     sys.path.append(lldb_pythonpath)<br>
> > ><br>
> > > For the weird long path issue, I will follow-up with our build team, but definitely needs to resolve the BreakpointCreateByLocation() can't be called issue first.<br>
> > ><br>
> > > Thanks for any help!<br>
> > > Jeffrey<br>
> > ><br>
> > > On Thu, Oct 8, 2015 at 10:46 AM, Greg Clayton <<a href="mailto:gclayton@apple.com">gclayton@apple.com</a>> wrote:<br>
> > ><br>
> > > > On Oct 8, 2015, at 10:25 AM, Jeffrey Tan <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>> wrote:<br>
> > > ><br>
> > > > Thanks Greg. Here is the info:<br>
> > > > (lldb) br list --verbose<br>
> > > > Current breakpoints:<br>
> > > > 1: file = 'EATAnimatedView.m', line = 21<br>
> > > >     1.1:<br>
> > > >       module = /Users/jeffreytan/Library/Developer/CoreSimulator/Devices/12E85C41-A74F-45E1-8440-E7D08D8EB1FA/data/Containers/Bundle/Application/3BA10AF8-9B18-4FD8-8C76-EA25DE2F37E6/MPKEats.app/MPKEats<br>
> > > >       compile unit = EATAnimatedView.m<br>
> > > >       function = -[EATAnimatedView initWithFrame:imageNames:animationDuration:repeatCount:touchEnabled:]<br>
> > > >       location = ./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m:21<br>
> > > >       address = 0x0000000103deae42<br>
> > > >       resolved = true<br>
> > > >       hit count = 0<br>
> > > ><br>
> > ><br>
> > > Wow that is a lot of redundant ////'s. You should fix your build system to not do this for one, but I agree we need to deal with this.<br>
> > ><br>
> > > You can modify the following function:<br>
> > ><br>
> > > void<br>
> > > FileSpec::RemoveBackupDots (const ConstString &input_const_str, ConstString &result_const_str);<br>
> > ><br>
> > > To remove the redundant slashes and it might make things work. The thing that really worries me is that you still have a relative location in your sources:<br>
> > ><br>
> > > "./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m:21"<br>
> > ><br>
> > ><br>
> > > This should have been resolved from the DWARF using DW_AT_comp_dir. What should happen is your DWARF should have a compile unit like:<br>
> > ><br>
> > ><br>
> > > 0x0000000b: DW_TAG_compile_unit [1] *<br>
> > >             DW_AT_producer( "Apple LLVM version 7.x.x" )<br>
> > >             DW_AT_language( DW_LANG_ObjC )<br>
> > >             DW_AT_name( "./Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m" )<br>
> > >             DW_AT_stmt_list( 0x00000000 )<br>
> > >             DW_AT_comp_dir( "/tmp/build/foo/bar" )<br>
> > >             DW_AT_low_pc( 0x0000000100000b50 )<br>
> > >             DW_AT_high_pc( 0x0000000100000e62 )<br>
> > ><br>
> > ><br>
> > > So if the DW_AT_name of your compile unit is relative, we should have a DW_AT_comp_dir that is absolute. Put the two together and we should have a complete path that works.<br>
> > ><br>
> > > Can you send me your ELF file that contains the DWARF so I can look at it?<br>
> > ><br>
> > > > I think we should fix this full path matching issue. It is totally reasonable for debugger user to move source file from build location to another place. Also, this needs to be supported for source server scenario. As long as the source file's checksum matches what recorded in symbol file we should match it.<br>
> > > ><br>
> > > > I still need to figure out why "self.debugger.GetSelectedTarget().BreakpointCreateByLocation("EATAnimatedView.m", line)" not working issue. The callstack seems to indicate I passed wrong number of arguments into it.<br>
> > ><br>
> > > This might be a swig type map issue where "line" in the python is a long and we don't know how to convert it to be passed to a uint32_t. We have seen such issues if the past where if you variable is a long, integer or other, it might not convert to uint32_t correctly...<br>
> > ><br>
> > ><br>
> > > ><br>
> > > > Jeffrey<br>
> > > ><br>
> > > > On Thu, Oct 8, 2015 at 9:46 AM, Greg Clayton <<a href="mailto:gclayton@apple.com">gclayton@apple.com</a>> wrote:<br>
> > > > > On Oct 7, 2015, at 8:31 PM, Jeffrey Tan via lldb-dev <<a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a>> wrote:<br>
> > > > ><br>
> > > > > Hi,<br>
> > > > ><br>
> > > > > I am writing a python script to set source line breakpoint in ObjC on Mac OSX. But self.debugger.GetSelectedTarget().BreakpointCreateByLocation("EATAnimatedView.m", line) always fail. Any ideas?<br>
> > > ><br>
> > > > As long as you have a selected target, this should work as long as you have debug info that matches.<br>
> > > > ><br>
> > > > > Also, can I use full path instead of file basename?<br>
> > > ><br>
> > > > Yes you can, but it must match exactly if you use the full path.<br>
> > > ><br>
> > > > > In lldb, I found "b /Users/jeffreytan/fbsource/fbobjc/Apps/Internal/MPKEats/MPKEats/View/EATAnimatedView.m:21" will fail to bind but "b EATAnimatedView.m:21" will succeed.<br>
> > > ><br>
> > > > This is usually because you have a makefile build system that is creating debug info that doesn't contain a path that matches. When you launch a compiler, it can often end up with different paths than what you think you have. So set the breakpoint by basename first, then do:<br>
> > > ><br>
> > > > (lldb) b main.c:12<br>
> > > > Breakpoint 1: where = a.out`main + 70 at main.c:12, address = 0x0000000100000b96<br>
> > > > (lldb) breakpoint list --verbose<br>
> > > > Current breakpoints:<br>
> > > > 1: file = 'main.c', line = 12<br>
> > > >     1.1:<br>
> > > >       module = /Volumes/work/gclayton/Documents/src/args/a.out<br>
> > > >       compile unit = main.c<br>
> > > >       function = main<br>
> > > >       location = /Volumes/work/gclayton/Documents/src/args/main.c:12<br>
> > > >       address = a.out[0x0000000100000b96]<br>
> > > >       resolved = false<br>
> > > >       hit count = 0<br>
> > > ><br>
> > > ><br>
> > > > You will see the full path to your source file in the "location" value. You will probably notice that the path is different. We try to take care of removing and extra "../useless_dir" things from the paths and still make things match, but you might have a case that we aren't handling. Let me know what you see when you set the breakpoint by basename.<br>
> > > ><br>
> > > ><br>
> > > > > Traceback (most recent call last):<br>
> > > > >   File "/Users/jeffreytan/fbsource/fbobjc/Tools/Nuclide/pkg/nuclide/debugger/lldb/scripts/chromedebugger.py", line 69, in _generate_response<br>
> > > > >     params=message.get('params', {}),<br>
> > > > >   File "/Users/jeffreytan/fbsource/fbobjc/Tools/Nuclide/pkg/nuclide/debugger/lldb/scripts/handler.py", line 42, in handle<br>
> > > > >     return self._domains[domain_name].handle(method_name, params)<br>
> > > > >   File "/Users/jeffreytan/fbsource/fbobjc/Tools/Nuclide/pkg/nuclide/debugger/lldb/scripts/handler.py", line 106, in handle<br>
> > > > >     return self._handlers[method](params)<br>
> > > > >   File "/Users/jeffreytan/fbsource/fbobjc/Tools/Nuclide/pkg/nuclide/debugger/lldb/scripts/handler.py", line 56, in _handler_wrapper<br>
> > > > >     ret = func(self, params)<br>
> > > > >   File "/Users/jeffreytan/fbsource/fbobjc/Tools/Nuclide/pkg/nuclide/debugger/lldb/scripts/debugger.py", line 248, in setBreakpointByUrl<br>
> > > > >     int(params['lineNumber']) + 1)<br>
> > > > >   File "/Users/jeffreytan/fbsource/fbobjc/Tools/Nuclide/pkg/nuclide/debugger/lldb/scripts/debugger.py", line 283, in _set_breakpoint_by_filespec<br>
> > > > >     breakpoint = self.debugger.GetSelectedTarget().BreakpointCreateByLocation(filespec, line)<br>
> > > > >   File "/Applications/Xcode.app/Contents/Developer/../SharedFrameworks/LLDB.framework/Resources/Python/lldb/__init__.py", line 8650, in BreakpointCreateByLocation<br>
> > > > >     return _lldb.SBTarget_BreakpointCreateByLocation(self, *args)<br>
> > > > > NotImplementedError: Wrong number of arguments for overloaded function 'SBTarget_BreakpointCreateByLocation'.<br>
> > > > >   Possible C/C++ prototypes are:<br>
> > > > >     BreakpointCreateByLocation(lldb::SBTarget *,char const *,uint32_t)<br>
> > > > >     BreakpointCreateByLocation(lldb::SBTarget *,lldb::SBFileSpec const &,uint32_t)<br>
> > > > > _______________________________________________<br>
> > > > > lldb-dev mailing list<br>
> > > > > <a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a><br>
> > > > > <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev</a><br>
> > > ><br>
> > > ><br>
> > ><br>
> > ><br>
> > ><br>
> > ><br>
> ><br>
> ><br>
><br>
><br>
<br>
</div></div></blockquote></div><br></div>