blob: d3eb735ccdb015f2752fc74881185dc4798b9682 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:241//===-- Target.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 "lldb/Target/Target.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Breakpoint/BreakpointResolver.h"
17#include "lldb/Breakpoint/BreakpointResolverAddress.h"
18#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
19#include "lldb/Breakpoint/BreakpointResolverName.h"
20#include "lldb/Core/Event.h"
21#include "lldb/Core/Log.h"
22#include "lldb/Core/Timer.h"
23#include "lldb/Core/StreamString.h"
24#include "lldb/Host/Host.h"
25#include "lldb/lldb-private-log.h"
26#include "lldb/Symbol/ObjectFile.h"
27#include "lldb/Target/Process.h"
28#include "lldb/Core/Debugger.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33//----------------------------------------------------------------------
34// Target constructor
35//----------------------------------------------------------------------
Greg Clayton66111032010-06-23 01:19:2936Target::Target(Debugger &debugger) :
Chris Lattner30fdc8d2010-06-08 16:52:2437 Broadcaster("Target"),
Greg Clayton66111032010-06-23 01:19:2938 m_debugger (debugger),
Chris Lattner30fdc8d2010-06-08 16:52:2439 m_images(),
40 m_breakpoint_list (false),
41 m_internal_breakpoint_list (true),
42 m_process_sp(),
43 m_triple(),
44 m_search_filter_sp(),
45 m_image_search_paths (ImageSearchPathsChanged, this),
46 m_scratch_ast_context_ap(NULL)
47{
48 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
49 if (log)
50 log->Printf ("%p Target::Target()", this);
51}
52
53//----------------------------------------------------------------------
54// Destructor
55//----------------------------------------------------------------------
56Target::~Target()
57{
58 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
59 if (log)
60 log->Printf ("%p Target::~Target()", this);
61 DeleteCurrentProcess ();
62}
63
64void
65Target::Dump (Stream *s)
66{
67 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
68 s->Indent();
69 s->PutCString("Target\n");
70 s->IndentMore();
71 m_images.Dump(s);
72 m_breakpoint_list.Dump(s);
73 m_internal_breakpoint_list.Dump(s);
74// if (m_process_sp.get())
75// m_process_sp->Dump(s);
76 s->IndentLess();
77}
78
79void
80Target::DeleteCurrentProcess ()
81{
82 if (m_process_sp.get())
83 {
84 if (m_process_sp->IsAlive())
85 m_process_sp->Destroy();
86 else
87 m_process_sp->Finalize();
88
89 // Do any cleanup of the target we need to do between process instances.
90 // NB It is better to do this before destroying the process in case the
91 // clean up needs some help from the process.
92 m_breakpoint_list.ClearAllBreakpointSites();
93 m_internal_breakpoint_list.ClearAllBreakpointSites();
94 m_process_sp.reset();
95 }
96}
97
98const lldb::ProcessSP &
99Target::CreateProcess (Listener &listener, const char *plugin_name)
100{
101 DeleteCurrentProcess ();
102 m_process_sp.reset(Process::FindPlugin(*this, plugin_name, listener));
103 return m_process_sp;
104}
105
106const lldb::ProcessSP &
107Target::GetProcessSP () const
108{
109 return m_process_sp;
110}
111
112lldb::TargetSP
113Target::GetSP()
114{
Greg Clayton66111032010-06-23 01:19:29115 return m_debugger.GetTargetList().GetTargetSP(this);
Chris Lattner30fdc8d2010-06-08 16:52:24116}
117
118BreakpointList &
119Target::GetBreakpointList(bool internal)
120{
121 if (internal)
122 return m_internal_breakpoint_list;
123 else
124 return m_breakpoint_list;
125}
126
127const BreakpointList &
128Target::GetBreakpointList(bool internal) const
129{
130 if (internal)
131 return m_internal_breakpoint_list;
132 else
133 return m_breakpoint_list;
134}
135
136BreakpointSP
137Target::GetBreakpointByID (break_id_t break_id)
138{
139 BreakpointSP bp_sp;
140
141 if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
142 bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
143 else
144 bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
145
146 return bp_sp;
147}
148
149BreakpointSP
150Target::CreateBreakpoint (const FileSpec *containingModule, const FileSpec &file, uint32_t line_no, bool check_inlines, bool internal)
151{
152 SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
153 BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine (NULL, file, line_no, check_inlines));
154 return CreateBreakpoint (filter_sp, resolver_sp, internal);
155}
156
157
158BreakpointSP
159Target::CreateBreakpoint (lldb::addr_t load_addr, bool internal)
160{
161 BreakpointSP bp_sp;
162 Address so_addr;
163 // Attempt to resolve our load address if possible, though it is ok if
164 // it doesn't resolve to section/offset.
165
166 Process *process = GetProcessSP().get();
167 if (process && process->ResolveLoadAddress(load_addr, so_addr))
168 bp_sp = CreateBreakpoint(so_addr, internal);
169 return bp_sp;
170}
171
172BreakpointSP
173Target::CreateBreakpoint (Address &addr, bool internal)
174{
175 TargetSP target_sp = this->GetSP();
176 SearchFilterSP filter_sp(new SearchFilter (target_sp));
177 BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
178 return CreateBreakpoint (filter_sp, resolver_sp, internal);
179}
180
181BreakpointSP
Greg Clayton0c5cd902010-06-28 21:30:43182Target::CreateBreakpoint (FileSpec *containingModule, const char *func_name, uint32_t func_name_type_mask, bool internal)
Chris Lattner30fdc8d2010-06-08 16:52:24183{
Greg Clayton0c5cd902010-06-28 21:30:43184 BreakpointSP bp_sp;
185 if (func_name)
186 {
187 SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
188 BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_name, func_name_type_mask, Breakpoint::Exact));
189 bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal);
190 }
191 return bp_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24192}
193
194
195SearchFilterSP
196Target::GetSearchFilterForModule (const FileSpec *containingModule)
197{
198 SearchFilterSP filter_sp;
199 lldb::TargetSP target_sp = this->GetSP();
200 if (containingModule != NULL)
201 {
202 // TODO: We should look into sharing module based search filters
203 // across many breakpoints like we do for the simple target based one
204 filter_sp.reset (new SearchFilterByModule (target_sp, *containingModule));
205 }
206 else
207 {
208 if (m_search_filter_sp.get() == NULL)
209 m_search_filter_sp.reset (new SearchFilter (target_sp));
210 filter_sp = m_search_filter_sp;
211 }
212 return filter_sp;
213}
214
215BreakpointSP
216Target::CreateBreakpoint (FileSpec *containingModule, RegularExpression &func_regex, bool internal)
217{
218 SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
219 BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, func_regex));
220
221 return CreateBreakpoint (filter_sp, resolver_sp, internal);
222}
223
224BreakpointSP
225Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal)
226{
227 BreakpointSP bp_sp;
228 if (filter_sp && resolver_sp)
229 {
230 bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp));
231 resolver_sp->SetBreakpoint (bp_sp.get());
232
233 if (internal)
234 m_internal_breakpoint_list.Add (bp_sp);
235 else
236 m_breakpoint_list.Add (bp_sp);
237
238 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
239 if (log)
240 {
241 StreamString s;
242 bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
243 log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, internal ? "yes" : "no", s.GetData());
244 }
245
246 // Broadcast the breakpoint creation event.
247 if (!internal && EventTypeHasListeners(eBroadcastBitBreakpointChanged))
248 {
249 BroadcastEvent (eBroadcastBitBreakpointChanged,
250 new Breakpoint::BreakpointEventData (Breakpoint::BreakpointEventData::eBreakpointAdded, bp_sp));
251 }
252
253 bp_sp->ResolveBreakpoint();
254 }
255 return bp_sp;
256}
257
258void
259Target::RemoveAllBreakpoints (bool internal_also)
260{
261 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
262 if (log)
263 log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
264
265 m_breakpoint_list.RemoveAll();
266 if (internal_also)
267 m_internal_breakpoint_list.RemoveAll();
268}
269
270void
271Target::DisableAllBreakpoints (bool internal_also)
272{
273 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
274 if (log)
275 log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
276
277 m_breakpoint_list.SetEnabledAll (false);
278 if (internal_also)
279 m_internal_breakpoint_list.SetEnabledAll (false);
280}
281
282void
283Target::EnableAllBreakpoints (bool internal_also)
284{
285 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
286 if (log)
287 log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
288
289 m_breakpoint_list.SetEnabledAll (true);
290 if (internal_also)
291 m_internal_breakpoint_list.SetEnabledAll (true);
292}
293
294bool
295Target::RemoveBreakpointByID (break_id_t break_id)
296{
297 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
298 if (log)
299 log->Printf ("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, break_id, LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
300
301 if (DisableBreakpointByID (break_id))
302 {
303 if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
304 m_internal_breakpoint_list.Remove(break_id);
305 else
306 m_breakpoint_list.Remove(break_id);
307 return true;
308 }
309 return false;
310}
311
312bool
313Target::DisableBreakpointByID (break_id_t break_id)
314{
315 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
316 if (log)
317 log->Printf ("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, break_id, LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
318
319 BreakpointSP bp_sp;
320
321 if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
322 bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
323 else
324 bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
325 if (bp_sp)
326 {
327 bp_sp->SetEnabled (false);
328 return true;
329 }
330 return false;
331}
332
333bool
334Target::EnableBreakpointByID (break_id_t break_id)
335{
336 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
337 if (log)
338 log->Printf ("Target::%s (break_id = %i, internal = %s)\n",
339 __FUNCTION__,
340 break_id,
341 LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
342
343 BreakpointSP bp_sp;
344
345 if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
346 bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
347 else
348 bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
349
350 if (bp_sp)
351 {
352 bp_sp->SetEnabled (true);
353 return true;
354 }
355 return false;
356}
357
358ModuleSP
359Target::GetExecutableModule ()
360{
361 ModuleSP executable_sp;
362 if (m_images.GetSize() > 0)
363 executable_sp = m_images.GetModuleAtIndex(0);
364 return executable_sp;
365}
366
367void
368Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
369{
370 m_images.Clear();
371 m_scratch_ast_context_ap.reset();
372
373 if (executable_sp.get())
374 {
375 Timer scoped_timer (__PRETTY_FUNCTION__,
376 "Target::SetExecutableModule (executable = '%s/%s')",
377 executable_sp->GetFileSpec().GetDirectory().AsCString(),
378 executable_sp->GetFileSpec().GetFilename().AsCString());
379
380 m_images.Append(executable_sp); // The first image is our exectuable file
381
382 ArchSpec exe_arch = executable_sp->GetArchitecture();
383 FileSpecList dependent_files;
384 ObjectFile * executable_objfile = executable_sp->GetObjectFile();
385 if (executable_objfile == NULL)
386 {
387
388 FileSpec bundle_executable(executable_sp->GetFileSpec());
389 if (Host::ResolveExecutableInBundle (&bundle_executable))
390 {
391 ModuleSP bundle_exe_module_sp(GetSharedModule(bundle_executable,
392 exe_arch));
393 SetExecutableModule (bundle_exe_module_sp, get_dependent_files);
394 if (bundle_exe_module_sp->GetObjectFile() != NULL)
395 executable_sp = bundle_exe_module_sp;
396 return;
397 }
398 }
399
400 if (executable_objfile)
401 {
402 executable_objfile->GetDependentModules(dependent_files);
403 for (uint32_t i=0; i<dependent_files.GetSize(); i++)
404 {
405 ModuleSP image_module_sp(GetSharedModule(dependent_files.GetFileSpecPointerAtIndex(i),
406 exe_arch));
407 if (image_module_sp.get())
408 {
409 //image_module_sp->Dump(&s);// REMOVE THIS, DEBUG ONLY
410 ObjectFile *objfile = image_module_sp->GetObjectFile();
411 if (objfile)
412 objfile->GetDependentModules(dependent_files);
413 }
414 }
415 }
416
417 // Now see if we know the target triple, and if so, create our scratch AST context:
418 ConstString target_triple;
419 if (GetTargetTriple(target_triple))
420 {
421 m_scratch_ast_context_ap.reset (new ClangASTContext(target_triple.GetCString()));
422 }
423 }
424}
425
426
427ModuleList&
428Target::GetImages ()
429{
430 return m_images;
431}
432
433ArchSpec
434Target::GetArchitecture () const
435{
436 ArchSpec arch;
437 if (m_images.GetSize() > 0)
438 {
439 Module *exe_module = m_images.GetModulePointerAtIndex(0);
440 if (exe_module)
441 arch = exe_module->GetArchitecture();
442 }
443 return arch;
444}
445
446
447
448bool
449Target::GetTargetTriple(ConstString &triple)
450{
451 triple.Clear();
452
453 if (m_triple)
454 {
455 triple = m_triple;
456 }
457 else
458 {
459 Module *exe_module = GetExecutableModule().get();
460 if (exe_module)
461 {
462 ObjectFile *objfile = exe_module->GetObjectFile();
463 if (objfile)
464 {
465 objfile->GetTargetTriple(m_triple);
466 triple = m_triple;
467 }
468 }
469 }
470 return !triple.IsEmpty();
471}
472
473void
474Target::ModuleAdded (ModuleSP &module_sp)
475{
476 // A module is being added to this target for the first time
477 ModuleList module_list;
478 module_list.Append(module_sp);
479 ModulesDidLoad (module_list);
480}
481
482void
483Target::ModuleUpdated (ModuleSP &old_module_sp, ModuleSP &new_module_sp)
484{
485 // A module is being added to this target for the first time
486 ModuleList module_list;
487 module_list.Append (old_module_sp);
488 ModulesDidUnload (module_list);
489 module_list.Clear ();
490 module_list.Append (new_module_sp);
491 ModulesDidLoad (module_list);
492}
493
494void
495Target::ModulesDidLoad (ModuleList &module_list)
496{
497 m_breakpoint_list.UpdateBreakpoints (module_list, true);
498 // TODO: make event data that packages up the module_list
499 BroadcastEvent (eBroadcastBitModulesLoaded, NULL);
500}
501
502void
503Target::ModulesDidUnload (ModuleList &module_list)
504{
505 m_breakpoint_list.UpdateBreakpoints (module_list, false);
506 // TODO: make event data that packages up the module_list
507 BroadcastEvent (eBroadcastBitModulesUnloaded, NULL);
508}
509
Chris Lattner30fdc8d2010-06-08 16:52:24510size_t
Greg Clayton35f3dd22010-06-30 23:04:24511Target::ReadMemory (const Address& addr, void *dst, size_t dst_len, Error &error)
Chris Lattner30fdc8d2010-06-08 16:52:24512{
Chris Lattner30fdc8d2010-06-08 16:52:24513 error.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24514
Greg Claytondda4f7b2010-06-30 23:03:03515 bool process_is_valid = m_process_sp && m_process_sp->IsAlive();
516
517 Address resolved_addr(addr);
518 if (!resolved_addr.IsSectionOffset())
519 {
520 if (process_is_valid)
Chris Lattner30fdc8d2010-06-08 16:52:24521 {
Greg Claytondda4f7b2010-06-30 23:03:03522 m_process_sp->ResolveLoadAddress (addr.GetOffset(), resolved_addr);
523 }
524 else
525 {
526 m_images.ResolveFileAddress(addr.GetOffset(), resolved_addr);
527 }
528 }
529
530
531 if (process_is_valid)
532 {
533 lldb::addr_t load_addr = resolved_addr.GetLoadAddress(m_process_sp.get());
534 if (load_addr == LLDB_INVALID_ADDRESS)
535 {
536 if (resolved_addr.GetModule() && resolved_addr.GetModule()->GetFileSpec())
537 error.SetErrorStringWithFormat("%s[0x%llx] can't be resolved, %s in not currently loaded.\n",
538 resolved_addr.GetModule()->GetFileSpec().GetFilename().AsCString(),
539 resolved_addr.GetFileAddress());
540 else
541 error.SetErrorStringWithFormat("0x%llx can't be resolved.\n", resolved_addr.GetFileAddress());
542 }
543 else
544 {
545 size_t bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error);
Chris Lattner30fdc8d2010-06-08 16:52:24546 if (bytes_read != dst_len)
547 {
548 if (error.Success())
549 {
550 if (bytes_read == 0)
Greg Claytondda4f7b2010-06-30 23:03:03551 error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", load_addr);
Chris Lattner30fdc8d2010-06-08 16:52:24552 else
Greg Claytondda4f7b2010-06-30 23:03:03553 error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, load_addr);
Chris Lattner30fdc8d2010-06-08 16:52:24554 }
555 }
Greg Claytondda4f7b2010-06-30 23:03:03556 if (bytes_read)
557 return bytes_read;
558 // If the address is not section offset we have an address that
559 // doesn't resolve to any address in any currently loaded shared
560 // libaries and we failed to read memory so there isn't anything
561 // more we can do. If it is section offset, we might be able to
562 // read cached memory from the object file.
563 if (!resolved_addr.IsSectionOffset())
564 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24565 }
Chris Lattner30fdc8d2010-06-08 16:52:24566 }
Greg Claytondda4f7b2010-06-30 23:03:03567
568 const Section *section = resolved_addr.GetSection();
569 if (section && section->GetModule())
570 {
571 ObjectFile *objfile = section->GetModule()->GetObjectFile();
572 return section->ReadSectionDataFromObjectFile (objfile,
573 resolved_addr.GetOffset(),
574 dst,
575 dst_len);
576 }
577 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24578}
579
580
581ModuleSP
582Target::GetSharedModule
583(
584 const FileSpec& file_spec,
585 const ArchSpec& arch,
586 const UUID *uuid_ptr,
587 const ConstString *object_name,
588 off_t object_offset,
589 Error *error_ptr
590)
591{
592 // Don't pass in the UUID so we can tell if we have a stale value in our list
593 ModuleSP old_module_sp; // This will get filled in if we have a new version of the library
594 bool did_create_module = false;
595 ModuleSP module_sp;
596
597 // If there are image search path entries, try to use them first to acquire a suitable image.
598
599 Error error;
600
601 if (m_image_search_paths.GetSize())
602 {
603 FileSpec transformed_spec;
604 if (m_image_search_paths.RemapPath (file_spec.GetDirectory(), transformed_spec.GetDirectory()))
605 {
606 transformed_spec.GetFilename() = file_spec.GetFilename();
607 error = ModuleList::GetSharedModule (transformed_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module);
608 }
609 }
610
611 // If a module hasn't been found yet, use the unmodified path.
612
613 if (!module_sp)
614 {
615 error = (ModuleList::GetSharedModule (file_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module));
616 }
617
618 if (module_sp)
619 {
620 m_images.Append (module_sp);
621 if (did_create_module)
622 {
623 if (old_module_sp && m_images.GetIndexForModule (old_module_sp.get()) != LLDB_INVALID_INDEX32)
624 ModuleUpdated(old_module_sp, module_sp);
625 else
626 ModuleAdded(module_sp);
627 }
628 }
629 if (error_ptr)
630 *error_ptr = error;
631 return module_sp;
632}
633
634
635Target *
636Target::CalculateTarget ()
637{
638 return this;
639}
640
641Process *
642Target::CalculateProcess ()
643{
644 return NULL;
645}
646
647Thread *
648Target::CalculateThread ()
649{
650 return NULL;
651}
652
653StackFrame *
654Target::CalculateStackFrame ()
655{
656 return NULL;
657}
658
659void
660Target::Calculate (ExecutionContext &exe_ctx)
661{
662 exe_ctx.target = this;
663 exe_ctx.process = NULL; // Do NOT fill in process...
664 exe_ctx.thread = NULL;
665 exe_ctx.frame = NULL;
666}
667
668PathMappingList &
669Target::GetImageSearchPathList ()
670{
671 return m_image_search_paths;
672}
673
674void
675Target::ImageSearchPathsChanged
676(
677 const PathMappingList &path_list,
678 void *baton
679)
680{
681 Target *target = (Target *)baton;
682 if (target->m_images.GetSize() > 1)
683 {
684 ModuleSP exe_module_sp (target->GetExecutableModule());
685 if (exe_module_sp)
686 {
687 target->m_images.Clear();
688 target->SetExecutableModule (exe_module_sp, true);
689 }
690 }
691}
692
693ClangASTContext *
694Target::GetScratchClangASTContext()
695{
696 return m_scratch_ast_context_ap.get();
697}