<rdar://problem/11072382>

Fixed a case where the source path remappings on the module were too expensive to
use when we try to verify (stat the file system) that the remapped path points to
a valid file. Now we will use the lldb_private::Module path remappings (if any) when
parsing the debug info without verifying that the paths exist so we don't slow down
line table parsing speeds.

llvm-svn: 153059
This commit is contained in:
Greg Clayton
2012-03-19 22:22:41 +00:00
parent c4aa60ffe9
commit f9be693369
6 changed files with 128 additions and 15 deletions

View File

@@ -1020,9 +1020,50 @@ public:
return m_source_mappings;
}
//------------------------------------------------------------------
/// Finds a source file given a file spec using the module source
/// path remappings (if any).
///
/// Tries to resolve \a orig_spec by checking the module source path
/// remappings. It makes sure the file exists, so this call can be
/// expensive if the remappings are on a network file system, so
/// use this function sparingly (not in a tight debug info parsing
/// loop).
///
/// @param[in] orig_spec
/// The original source file path to try and remap.
///
/// @param[out] new_spec
/// The newly remapped filespec that is guaranteed to exist.
///
/// @return
/// /b true if \a orig_spec was successfully located and
/// \a new_spec is filled in with an existing file spec,
/// \b false otherwise.
//------------------------------------------------------------------
bool
FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const;
//------------------------------------------------------------------
/// Remaps a source file given \a path into \a new_path.
///
/// Remaps \a path if any source remappings match. This function
/// does NOT stat the file system so it can be used in tight loops
/// where debug info is being parsed.
///
/// @param[in] path
/// The original source file path to try and remap.
///
/// @param[out] new_path
/// The newly remapped filespec that is may or may not exist.
///
/// @return
/// /b true if \a path was successfully located and \a new_path
/// is filled in with a new source path, \b false otherwise.
//------------------------------------------------------------------
bool
RemapSourceFile (const char *path, std::string &new_path) const;
protected:
//------------------------------------------------------------------
// Member Variables

View File

@@ -86,6 +86,47 @@ public:
bool
RemapPath (const ConstString &path, ConstString &new_path) const;
//------------------------------------------------------------------
/// Remaps a source file given \a path into \a new_path.
///
/// Remaps \a path if any source remappings match. This function
/// does NOT stat the file system so it can be used in tight loops
/// where debug info is being parsed.
///
/// @param[in] path
/// The original source file path to try and remap.
///
/// @param[out] new_path
/// The newly remapped filespec that is may or may not exist.
///
/// @return
/// /b true if \a path was successfully located and \a new_path
/// is filled in with a new source path, \b false otherwise.
//------------------------------------------------------------------
bool
RemapPath (const char *path, std::string &new_path) const;
//------------------------------------------------------------------
/// Finds a source file given a file spec using the path remappings.
///
/// Tries to resolve \a orig_spec by checking the path remappings.
/// It makes sure the file exists by checking with the file system,
/// so this call can be expensive if the remappings are on a network
/// or are even on the local file system, so use this function
/// sparingly (not in a tight debug info parsing loop).
///
/// @param[in] orig_spec
/// The original source file path to try and remap.
///
/// @param[out] new_spec
/// The newly remapped filespec that is guaranteed to exist.
///
/// @return
/// /b true if \a orig_spec was successfully located and
/// \a new_spec is filled in with an existing file spec,
/// \b false otherwise.
//------------------------------------------------------------------
bool
FindFile (const FileSpec &orig_spec, FileSpec &new_spec) const;

View File

@@ -1165,3 +1165,10 @@ Module::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const
return m_source_mappings.FindFile (orig_spec, new_spec);
}
bool
Module::RemapSourceFile (const char *path, std::string &new_path) const
{
Mutex::Locker locker (m_mutex);
return m_source_mappings.RemapPath(path, new_path);
}

View File

@@ -497,6 +497,7 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
break;
}
std::string fullpath;
std::string remapped_fullpath;
while (offset < end_prologue_offset)
{
const char* path = debug_line_data.GetCStr( &offset );
@@ -509,7 +510,10 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
if (path[0] == '/')
{
// The path starts with a directory delimiter, so we are done.
fullpath = path;
if (module_sp->RemapSourceFile (path, fullpath))
support_files.Append(FileSpec (fullpath.c_str(), false));
else
support_files.Append(FileSpec (path, false));
}
else
{
@@ -538,16 +542,12 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
fullpath += '/';
}
fullpath += path;
if (module_sp->RemapSourceFile (fullpath.c_str(), remapped_fullpath))
support_files.Append(FileSpec (remapped_fullpath.c_str(), false));
else
support_files.Append(FileSpec (fullpath.c_str(), false));
}
// We don't need to realpath files in the debug_line tables.
FileSpec file_spec(fullpath.c_str(), false);
FileSpec remapped_file_spec;
if (module_sp->FindSourceFile(file_spec, remapped_file_spec))
support_files.Append(remapped_file_spec);
else
support_files.Append(file_spec);
}
}

View File

@@ -723,13 +723,17 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* curr_cu, CompUnitSP& compil
LanguageType cu_language = (LanguageType)cu_die->GetAttributeValueAsUnsigned(this, curr_cu, DW_AT_language, 0);
if (cu_die_name)
{
std::string ramapped_file;
FileSpec cu_file_spec;
if (cu_die_name[0] == '/' || cu_comp_dir == NULL || cu_comp_dir[0] == '\0')
{
// If we have a full path to the compile unit, we don't need to resolve
// the file. This can be expensive e.g. when the source files are NFS mounted.
cu_file_spec.SetFile (cu_die_name, false);
if (module_sp->RemapSourceFile(cu_die_name, ramapped_file))
cu_file_spec.SetFile (ramapped_file.c_str(), false);
else
cu_file_spec.SetFile (cu_die_name, false);
}
else
{
@@ -737,13 +741,12 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* curr_cu, CompUnitSP& compil
if (*fullpath.rbegin() != '/')
fullpath += '/';
fullpath += cu_die_name;
cu_file_spec.SetFile (fullpath.c_str(), false);
if (module_sp->RemapSourceFile (fullpath.c_str(), ramapped_file))
cu_file_spec.SetFile (ramapped_file.c_str(), false);
else
cu_file_spec.SetFile (fullpath.c_str(), false);
}
FileSpec remapped_file_spec;
if (module_sp->FindSourceFile(cu_file_spec, remapped_file_spec))
cu_file_spec = remapped_file_spec;
compile_unit_sp.reset(new CompileUnit (module_sp,
curr_cu,
cu_file_spec,

View File

@@ -173,6 +173,27 @@ PathMappingList::RemapPath (const ConstString &path, ConstString &new_path) cons
return false;
}
bool
PathMappingList::RemapPath (const char *path, std::string &new_path) const
{
if (!m_pairs.empty() || path == NULL || path[0] == '\0')
return false;
const_iterator pos, end = m_pairs.end();
for (pos = m_pairs.begin(); pos != end; ++pos)
{
const size_t prefix_len = pos->first.GetLength();
if (::strncmp (pos->first.GetCString(), path, prefix_len) == 0)
{
new_path = pos->second.GetCString();
new_path.append(path + prefix_len);
return true;
}
}
return false;
}
bool
PathMappingList::FindFile (const FileSpec &orig_spec, FileSpec &new_spec) const
{