blob: 270d7ed0f5daa6b295703bd256d9c53513f318f8 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- SymbolVendorMacOSX.cpp ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "SymbolVendorMacOSX.h"
11
12#include <mach/machine.h> // DebugSymbols needs this on Leopard...
13
14#include <AvailabilityMacros.h>
15
16#include "lldb/Core/Module.h"
17#include "lldb/Core/PluginManager.h"
18#include "lldb/Core/Section.h"
19#include "lldb/Core/Timer.h"
20#include "lldb/Host/Symbols.h"
21#include "lldb/Symbol/ObjectFile.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
26//----------------------------------------------------------------------
27// SymbolVendorMacOSX constructor
28//----------------------------------------------------------------------
29SymbolVendorMacOSX::SymbolVendorMacOSX(Module *module) :
30 SymbolVendor(module)
31{
32}
33
34//----------------------------------------------------------------------
35// Destructor
36//----------------------------------------------------------------------
37SymbolVendorMacOSX::~SymbolVendorMacOSX()
38{
39}
40
41
42static bool
43UUIDsMatch(Module *module, ObjectFile *ofile)
44{
45 if (module && ofile)
46 {
47 // Make sure the UUIDs match
48 UUID dsym_uuid;
49 if (ofile->GetUUID(&dsym_uuid))
50 return dsym_uuid == module->GetUUID();
51 }
52 return false;
53}
54
55
56//ObjectFile *
57//LocateDSYMMachFileInDSYMBundle (Module* module, FileSpec& dsym_fspec)
58//{
59// ObjectFile *dsym_objfile = NULL;
60//
61// char path[PATH_MAX];
62//
63// if (dsym_fspec.GetPath(path, sizeof(path)))
64// {
65// size_t path_len = strlen(path);
66// const char *bundle_subpath = "/Contents/Resources/DWARF/";
67// if (path_len > 0)
68// {
69// if (path[path_len-1] == '/')
70// ::strncat (path, bundle_subpath + 1, sizeof(path));
71// else
72// ::strncat (path, bundle_subpath, sizeof(path));
73// ::strncat (path, dsym_fspec.GetFilename().AsCString(), sizeof(path));
74//
75// path_len = strlen(path);
76//
77// if (::strcasecmp (&path[path_len - strlen(".dSYM")], ".dSYM") == 0)
78// {
79// path[path_len - ::strlen(".dSYM")] = '\0';
80// dsym_fspec.SetFile(path);
81// dsym_objfile = ObjectFile::FindPlugin(module, &dsym_fspec, 0);
82// }
83// }
84// }
85// return dsym_objfile;
86//}
87//
88//CFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url) __attribute__((weak_import));
89
90
91//ObjectFile *
92//FindDSYMUsingDebugSymbols (Module* module, FileSpec& dsym_fspec)
93//{
94// Timer scoped_locate("FindDSYMUsingDebugSymbols");
95// dsym_fspec.Clear();
96// ObjectFile *dsym_objfile = NULL;
97// if (module->GetUUID().IsValid())
98// {
99// // Try and locate the dSYM file using DebugSymbols first
100// const UInt8 *module_uuid = (const UInt8 *)module->GetUUID().GetBytes();
101// if (module_uuid != NULL)
102// {
103// CFUUIDRef module_uuid_ref;
104// module_uuid_ref = ::CFUUIDCreateWithBytes ( NULL,
105// module_uuid[0],
106// module_uuid[1],
107// module_uuid[2],
108// module_uuid[3],
109// module_uuid[4],
110// module_uuid[5],
111// module_uuid[6],
112// module_uuid[7],
113// module_uuid[8],
114// module_uuid[9],
115// module_uuid[10],
116// module_uuid[11],
117// module_uuid[12],
118// module_uuid[13],
119// module_uuid[14],
120// module_uuid[15]);
121//
122// if (module_uuid_ref)
123// {
124// CFURLRef dsym_url = NULL;
125// CFURLRef exec_url = NULL;
126//
127// // if (DBGCopyFullDSYMURLForUUID)
128// {
129// char exec_path[PATH_MAX];
130// if (module->GetFileSpec().GetPath(exec_path, sizeof(exec_path)))
131// {
132// exec_url = CFURLCreateFromFileSystemRepresentation ( NULL,
133// (const UInt8 *)exec_path,
134// strlen(exec_path),
135// FALSE);
136// }
137//
138// dsym_url = DBGCopyFullDSYMURLForUUID(module_uuid_ref, exec_url);
139// }
140// // else
141// // {
142// // dsym_url = DBGCopyDSYMURLForUUID(module_uuid_ref);
143// // }
144//
145// if (exec_url)
146// {
147// ::CFRelease (exec_url);
148// exec_url = NULL;
149// }
150//
151// ::CFRelease(module_uuid_ref);
152// module_uuid_ref = NULL;
153//
154// if (dsym_url)
155// {
156// char dsym_path[PATH_MAX];
157// Boolean success = CFURLGetFileSystemRepresentation (dsym_url, true, (UInt8*)dsym_path, sizeof(dsym_path)-1);
158//
159// ::CFRelease(dsym_url), dsym_url = NULL;
160//
161// if (success)
162// {
163// dsym_fspec.SetFile(dsym_path);
164//
165// // Some newer versions of DebugSymbols will return a full path into a dSYM bundle
166// // that points to the correct mach file within the dSYM bundle (MH_DSYM mach file
167// // type).
168// dsym_objfile = ObjectFile::FindPlugin(module, &dsym_fspec, 0);
169//
170// // Olders versions of DebugSymbols will return a path to a dSYM bundle.
171// if (dsym_objfile == NULL)
172// dsym_objfile = LocateDSYMMachFileInDSYMBundle (module, dsym_fspec);
173// }
174// }
175// }
176// }
177// }
178// return dsym_objfile;
179//}
180
181static void
182ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile *dsym_objfile)
183{
184 // We need both the executable and the dSYM to live off of the
185 // same section lists. So we take all of the sections from the
186 // executable, and replace them in the dSYM. This allows section
187 // offset addresses that come from the dSYM to automatically
188 // get updated as images (shared libraries) get loaded and
189 // unloaded.
190 SectionList *exec_section_list = exec_objfile->GetSectionList();
191 SectionList *dsym_section_list = dsym_objfile->GetSectionList();
192 if (exec_section_list && dsym_section_list)
193 {
194 const uint32_t num_exec_sections = dsym_section_list->GetSize();
195 uint32_t exec_sect_idx;
196 for (exec_sect_idx = 0; exec_sect_idx < num_exec_sections; ++exec_sect_idx)
197 {
198 SectionSP exec_sect_sp(exec_section_list->GetSectionAtIndex(exec_sect_idx));
199 if (exec_sect_sp.get())
200 {
201 // Try and replace any sections that exist in both the executable
202 // and in the dSYM with those from the executable. If we fail to
203 // replace the one in the dSYM, then add the executable section to
204 // the dSYM.
205 if (dsym_section_list->ReplaceSection(exec_sect_sp->GetID(), exec_sect_sp, 0) == false)
206 dsym_section_list->AddSection(exec_sect_sp);
207 }
208 }
209 }
210}
211
212void
213SymbolVendorMacOSX::Initialize()
214{
215 PluginManager::RegisterPlugin (GetPluginNameStatic(),
216 GetPluginDescriptionStatic(),
217 CreateInstance);
218}
219
220void
221SymbolVendorMacOSX::Terminate()
222{
223 PluginManager::UnregisterPlugin (CreateInstance);
224}
225
226
227const char *
228SymbolVendorMacOSX::GetPluginNameStatic()
229{
230 return "symbol-vendor.macosx";
231}
232
233const char *
234SymbolVendorMacOSX::GetPluginDescriptionStatic()
235{
236 return "Symbol vendor for MacOSX that looks for dSYM files that match executables.";
237}
238
239
240
241//----------------------------------------------------------------------
242// CreateInstance
243//
244// Platforms can register a callback to use when creating symbol
245// vendors to allow for complex debug information file setups, and to
246// also allow for finding separate debug information files.
247//----------------------------------------------------------------------
248SymbolVendor*
249SymbolVendorMacOSX::CreateInstance(Module* module)
250{
251 Timer scoped_timer (__PRETTY_FUNCTION__,
252 "SymbolVendorMacOSX::CreateInstance (module = %s/%s)",
253 module->GetFileSpec().GetDirectory().AsCString(),
254 module->GetFileSpec().GetFilename().AsCString());
255 SymbolVendorMacOSX* symbol_vendor = new SymbolVendorMacOSX(module);
256 if (symbol_vendor)
257 {
258 char path[PATH_MAX];
259 path[0] = '\0';
260
261 // Try and locate the dSYM file on Mac OS X
262 ObjectFile * obj_file = module->GetObjectFile();
263 if (obj_file)
264 {
265 Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM",
266 "SymbolVendorMacOSX::CreateInstance (module = %s/%s) locate dSYM",
267 module->GetFileSpec().GetDirectory().AsCString(),
268 module->GetFileSpec().GetFilename().AsCString());
269
270 FileSpec dsym_fspec;
271 std::auto_ptr<ObjectFile> dsym_objfile_ap;
272 const FileSpec &file_spec = obj_file->GetFileSpec();
273 if (file_spec)
274 {
275 dsym_fspec = Symbols::LocateExecutableSymbolFile (&file_spec, &module->GetArchitecture(), &module->GetUUID());
276
277 if (dsym_fspec)
278 {
279 dsym_objfile_ap.reset(ObjectFile::FindPlugin(module, &dsym_fspec, 0, dsym_fspec.GetByteSize()));
280 if (UUIDsMatch(module, dsym_objfile_ap.get()))
281 {
282 ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_ap.get());
283 symbol_vendor->AddSymbolFileRepresendation(dsym_objfile_ap.release());
284 return symbol_vendor;
285 }
286 }
287 }
288
289 // Just create our symbol vendor using the current objfile as this is either
290 // an executable with no dSYM (that we could locate), and executable with
291 // a dSYM that has a UUID that doesn't match, or it is a dSYM file itself.
292 symbol_vendor->AddSymbolFileRepresendation(obj_file);
293 }
294 }
295 return symbol_vendor;
296}
297
298
299
300//------------------------------------------------------------------
301// PluginInterface protocol
302//------------------------------------------------------------------
303const char *
304SymbolVendorMacOSX::GetPluginName()
305{
306 return "SymbolVendorMacOSX";
307}
308
309const char *
310SymbolVendorMacOSX::GetShortPluginName()
311{
312 return GetPluginNameStatic();
313}
314
315uint32_t
316SymbolVendorMacOSX::GetPluginVersion()
317{
318 return 1;
319}
320
321void
322SymbolVendorMacOSX::GetPluginCommandHelp (const char *command, Stream *strm)
323{
324}
325
326Error
327SymbolVendorMacOSX::ExecutePluginCommand (Args &command, Stream *strm)
328{
329 Error error;
330 error.SetErrorString("No plug-in command are currently supported.");
331 return error;
332}
333
334Log *
335SymbolVendorMacOSX::EnablePluginLogging (Stream *strm, Args &command)
336{
337 return NULL;
338}
339