xref: /freebsd/contrib/llvm-project/lldb/source/Symbol/FuncUnwinders.cpp (revision 2f513db72b034fd5ef7f080b11be5c711c15186a)
1 //===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Symbol/FuncUnwinders.h"
10 #include "lldb/Core/Address.h"
11 #include "lldb/Core/AddressRange.h"
12 #include "lldb/Symbol/ArmUnwindInfo.h"
13 #include "lldb/Symbol/CompactUnwindInfo.h"
14 #include "lldb/Symbol/DWARFCallFrameInfo.h"
15 #include "lldb/Symbol/ObjectFile.h"
16 #include "lldb/Symbol/SymbolFile.h"
17 #include "lldb/Symbol/UnwindPlan.h"
18 #include "lldb/Symbol/UnwindTable.h"
19 #include "lldb/Target/ABI.h"
20 #include "lldb/Target/ExecutionContext.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/RegisterNumber.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Target/UnwindAssembly.h"
27 
28 #include <memory>
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 /// constructor
34 
35 FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)
36     : m_unwind_table(unwind_table), m_range(range), m_mutex(),
37       m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(),
38       m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(),
39       m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(),
40       m_unwind_plan_arch_default_sp(),
41       m_unwind_plan_arch_default_at_func_entry_sp(),
42       m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false),
43       m_tried_unwind_plan_debug_frame(false),
44       m_tried_unwind_plan_eh_frame_augmented(false),
45       m_tried_unwind_plan_debug_frame_augmented(false),
46       m_tried_unwind_plan_compact_unwind(false),
47       m_tried_unwind_plan_arm_unwind(false),
48       m_tried_unwind_plan_symbol_file(false), m_tried_unwind_fast(false),
49       m_tried_unwind_arch_default(false),
50       m_tried_unwind_arch_default_at_func_entry(false),
51       m_first_non_prologue_insn() {}
52 
53 /// destructor
54 
55 FuncUnwinders::~FuncUnwinders() {}
56 
57 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target,
58                                                     Thread &thread) {
59   std::lock_guard<std::recursive_mutex> guard(m_mutex);
60 
61   if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread))
62     return plan_sp;
63   if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target))
64     return plan_sp;
65   if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target))
66     return plan_sp;
67   if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target))
68     return plan_sp;
69   if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target))
70     return plan_sp;
71 
72   return nullptr;
73 }
74 
75 UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target) {
76   std::lock_guard<std::recursive_mutex> guard(m_mutex);
77   if (m_unwind_plan_compact_unwind.size() > 0)
78     return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact
79                                             // unwind plans for one func
80   if (m_tried_unwind_plan_compact_unwind)
81     return UnwindPlanSP();
82 
83   m_tried_unwind_plan_compact_unwind = true;
84   if (m_range.GetBaseAddress().IsValid()) {
85     Address current_pc(m_range.GetBaseAddress());
86     CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
87     if (compact_unwind) {
88       UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric));
89       if (compact_unwind->GetUnwindPlan(target, current_pc, *unwind_plan_sp)) {
90         m_unwind_plan_compact_unwind.push_back(unwind_plan_sp);
91         return m_unwind_plan_compact_unwind[0]; // FIXME support multiple
92                                                 // compact unwind plans for one
93                                                 // func
94       }
95     }
96   }
97   return UnwindPlanSP();
98 }
99 
100 UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target) {
101   std::lock_guard<std::recursive_mutex> guard(m_mutex);
102   if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame)
103     return m_unwind_plan_eh_frame_sp;
104 
105   m_tried_unwind_plan_eh_frame = true;
106   if (m_range.GetBaseAddress().IsValid()) {
107     DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
108     if (eh_frame) {
109       m_unwind_plan_eh_frame_sp =
110           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
111       if (!eh_frame->GetUnwindPlan(m_range, *m_unwind_plan_eh_frame_sp))
112         m_unwind_plan_eh_frame_sp.reset();
113     }
114   }
115   return m_unwind_plan_eh_frame_sp;
116 }
117 
118 UnwindPlanSP FuncUnwinders::GetDebugFrameUnwindPlan(Target &target) {
119   std::lock_guard<std::recursive_mutex> guard(m_mutex);
120   if (m_unwind_plan_debug_frame_sp || m_tried_unwind_plan_debug_frame)
121     return m_unwind_plan_debug_frame_sp;
122 
123   m_tried_unwind_plan_debug_frame = true;
124   if (m_range.GetBaseAddress().IsValid()) {
125     DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo();
126     if (debug_frame) {
127       m_unwind_plan_debug_frame_sp =
128           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
129       if (!debug_frame->GetUnwindPlan(m_range, *m_unwind_plan_debug_frame_sp))
130         m_unwind_plan_debug_frame_sp.reset();
131     }
132   }
133   return m_unwind_plan_debug_frame_sp;
134 }
135 
136 UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target) {
137   std::lock_guard<std::recursive_mutex> guard(m_mutex);
138   if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)
139     return m_unwind_plan_arm_unwind_sp;
140 
141   m_tried_unwind_plan_arm_unwind = true;
142   if (m_range.GetBaseAddress().IsValid()) {
143     Address current_pc(m_range.GetBaseAddress());
144     ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
145     if (arm_unwind_info) {
146       m_unwind_plan_arm_unwind_sp =
147           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
148       if (!arm_unwind_info->GetUnwindPlan(target, current_pc,
149                                           *m_unwind_plan_arm_unwind_sp))
150         m_unwind_plan_arm_unwind_sp.reset();
151     }
152   }
153   return m_unwind_plan_arm_unwind_sp;
154 }
155 
156 namespace {
157 class RegisterContextToInfo: public SymbolFile::RegisterInfoResolver {
158 public:
159   RegisterContextToInfo(RegisterContext &ctx) : m_ctx(ctx) {}
160 
161   const RegisterInfo *ResolveName(llvm::StringRef name) const {
162     return m_ctx.GetRegisterInfoByName(name);
163   }
164   const RegisterInfo *ResolveNumber(lldb::RegisterKind kind,
165                                     uint32_t number) const {
166     return m_ctx.GetRegisterInfo(kind, number);
167   }
168 
169 private:
170   RegisterContext &m_ctx;
171 };
172 } // namespace
173 
174 UnwindPlanSP FuncUnwinders::GetSymbolFileUnwindPlan(Thread &thread) {
175   std::lock_guard<std::recursive_mutex> guard(m_mutex);
176   if (m_unwind_plan_symbol_file_sp.get() || m_tried_unwind_plan_symbol_file)
177     return m_unwind_plan_symbol_file_sp;
178 
179   m_tried_unwind_plan_symbol_file = true;
180   if (SymbolFile *symfile = m_unwind_table.GetSymbolFile()) {
181     m_unwind_plan_symbol_file_sp = symfile->GetUnwindPlan(
182         m_range.GetBaseAddress(),
183         RegisterContextToInfo(*thread.GetRegisterContext()));
184   }
185   return m_unwind_plan_symbol_file_sp;
186 }
187 
188 UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target,
189                                                           Thread &thread) {
190   std::lock_guard<std::recursive_mutex> guard(m_mutex);
191   if (m_unwind_plan_eh_frame_augmented_sp.get() ||
192       m_tried_unwind_plan_eh_frame_augmented)
193     return m_unwind_plan_eh_frame_augmented_sp;
194 
195   // Only supported on x86 architectures where we get eh_frame from the
196   // compiler that describes the prologue instructions perfectly, and sometimes
197   // the epilogue instructions too.
198   if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&
199       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&
200       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {
201     m_tried_unwind_plan_eh_frame_augmented = true;
202     return m_unwind_plan_eh_frame_augmented_sp;
203   }
204 
205   m_tried_unwind_plan_eh_frame_augmented = true;
206 
207   UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target);
208   if (!eh_frame_plan)
209     return m_unwind_plan_eh_frame_augmented_sp;
210 
211   m_unwind_plan_eh_frame_augmented_sp =
212       std::make_shared<UnwindPlan>(*eh_frame_plan);
213 
214   // Augment the eh_frame instructions with epilogue descriptions if necessary
215   // so the UnwindPlan can be used at any instruction in the function.
216 
217   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
218   if (assembly_profiler_sp) {
219     if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
220             m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) {
221       m_unwind_plan_eh_frame_augmented_sp.reset();
222     }
223   } else {
224     m_unwind_plan_eh_frame_augmented_sp.reset();
225   }
226   return m_unwind_plan_eh_frame_augmented_sp;
227 }
228 
229 UnwindPlanSP FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target,
230                                                              Thread &thread) {
231   std::lock_guard<std::recursive_mutex> guard(m_mutex);
232   if (m_unwind_plan_debug_frame_augmented_sp.get() ||
233       m_tried_unwind_plan_debug_frame_augmented)
234     return m_unwind_plan_debug_frame_augmented_sp;
235 
236   // Only supported on x86 architectures where we get debug_frame from the
237   // compiler that describes the prologue instructions perfectly, and sometimes
238   // the epilogue instructions too.
239   if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&
240       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&
241       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {
242     m_tried_unwind_plan_debug_frame_augmented = true;
243     return m_unwind_plan_debug_frame_augmented_sp;
244   }
245 
246   m_tried_unwind_plan_debug_frame_augmented = true;
247 
248   UnwindPlanSP debug_frame_plan = GetDebugFrameUnwindPlan(target);
249   if (!debug_frame_plan)
250     return m_unwind_plan_debug_frame_augmented_sp;
251 
252   m_unwind_plan_debug_frame_augmented_sp =
253       std::make_shared<UnwindPlan>(*debug_frame_plan);
254 
255   // Augment the debug_frame instructions with epilogue descriptions if
256   // necessary so the UnwindPlan can be used at any instruction in the
257   // function.
258 
259   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
260   if (assembly_profiler_sp) {
261     if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
262             m_range, thread, *m_unwind_plan_debug_frame_augmented_sp)) {
263       m_unwind_plan_debug_frame_augmented_sp.reset();
264     }
265   } else
266     m_unwind_plan_debug_frame_augmented_sp.reset();
267   return m_unwind_plan_debug_frame_augmented_sp;
268 }
269 
270 UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,
271                                                   Thread &thread) {
272   std::lock_guard<std::recursive_mutex> guard(m_mutex);
273   if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly ||
274       !m_unwind_table.GetAllowAssemblyEmulationUnwindPlans()) {
275     return m_unwind_plan_assembly_sp;
276   }
277 
278   m_tried_unwind_plan_assembly = true;
279 
280   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
281   if (assembly_profiler_sp) {
282     m_unwind_plan_assembly_sp =
283         std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
284     if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
285             m_range, thread, *m_unwind_plan_assembly_sp)) {
286       m_unwind_plan_assembly_sp.reset();
287     }
288   }
289   return m_unwind_plan_assembly_sp;
290 }
291 
292 // This method compares the pc unwind rule in the first row of two UnwindPlans.
293 // If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is
294 // sp"), then it will return LazyBoolTrue.
295 LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(
296     Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
297   LazyBool plans_are_identical = eLazyBoolCalculate;
298 
299   RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
300   uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB);
301 
302   if (a.get() && b.get()) {
303     UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0);
304     UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0);
305 
306     if (a_first_row.get() && b_first_row.get()) {
307       UnwindPlan::Row::RegisterLocation a_pc_regloc;
308       UnwindPlan::Row::RegisterLocation b_pc_regloc;
309 
310       a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc);
311       b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc);
312 
313       plans_are_identical = eLazyBoolYes;
314 
315       if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) {
316         plans_are_identical = eLazyBoolNo;
317       }
318       if (a_pc_regloc != b_pc_regloc) {
319         plans_are_identical = eLazyBoolNo;
320       }
321     }
322   }
323   return plans_are_identical;
324 }
325 
326 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target,
327                                                        Thread &thread) {
328   UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target);
329   if (!eh_frame_sp)
330     eh_frame_sp = GetDebugFrameUnwindPlan(target);
331   UnwindPlanSP arch_default_at_entry_sp =
332       GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread);
333   UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread);
334   UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan(target, thread);
335 
336   // This point of this code is to detect when a function is using a non-
337   // standard ABI, and the eh_frame correctly describes that alternate ABI.
338   // This is addressing a specific situation on x86_64 linux systems where one
339   // function in a library pushes a value on the stack and jumps to another
340   // function.  So using an assembly instruction based unwind will not work
341   // when you're in the second function - the stack has been modified in a non-
342   // ABI way.  But we have eh_frame that correctly describes how to unwind from
343   // this location.  So we're looking to see if the initial pc register save
344   // location from the eh_frame is different from the assembly unwind, the arch
345   // default unwind, and the arch default at initial function entry.
346   //
347   // We may have eh_frame that describes the entire function -- or we may have
348   // eh_frame that only describes the unwind after the prologue has executed --
349   // so we need to check both the arch default (once the prologue has executed)
350   // and the arch default at initial function entry.  And we may be running on
351   // a target where we have only some of the assembly/arch default unwind plans
352   // available.
353 
354   if (CompareUnwindPlansForIdenticalInitialPCLocation(
355           thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&
356       CompareUnwindPlansForIdenticalInitialPCLocation(
357           thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&
358       CompareUnwindPlansForIdenticalInitialPCLocation(
359           thread, assembly_sp, arch_default_sp) == eLazyBoolNo) {
360     return eh_frame_sp;
361   }
362 
363   if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread))
364     return plan_sp;
365   if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread))
366     return plan_sp;
367   if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread))
368     return plan_sp;
369 
370   return assembly_sp;
371 }
372 
373 UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target,
374                                                     Thread &thread) {
375   std::lock_guard<std::recursive_mutex> guard(m_mutex);
376   if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)
377     return m_unwind_plan_fast_sp;
378 
379   m_tried_unwind_fast = true;
380 
381   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
382   if (assembly_profiler_sp) {
383     m_unwind_plan_fast_sp =
384         std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
385     if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,
386                                                  *m_unwind_plan_fast_sp)) {
387       m_unwind_plan_fast_sp.reset();
388     }
389   }
390   return m_unwind_plan_fast_sp;
391 }
392 
393 UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) {
394   std::lock_guard<std::recursive_mutex> guard(m_mutex);
395   if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)
396     return m_unwind_plan_arch_default_sp;
397 
398   m_tried_unwind_arch_default = true;
399 
400   Address current_pc;
401   ProcessSP process_sp(thread.CalculateProcess());
402   if (process_sp) {
403     ABI *abi = process_sp->GetABI().get();
404     if (abi) {
405       m_unwind_plan_arch_default_sp =
406           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
407       if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) {
408         m_unwind_plan_arch_default_sp.reset();
409       }
410     }
411   }
412 
413   return m_unwind_plan_arch_default_sp;
414 }
415 
416 UnwindPlanSP
417 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) {
418   std::lock_guard<std::recursive_mutex> guard(m_mutex);
419   if (m_unwind_plan_arch_default_at_func_entry_sp.get() ||
420       m_tried_unwind_arch_default_at_func_entry)
421     return m_unwind_plan_arch_default_at_func_entry_sp;
422 
423   m_tried_unwind_arch_default_at_func_entry = true;
424 
425   Address current_pc;
426   ProcessSP process_sp(thread.CalculateProcess());
427   if (process_sp) {
428     ABI *abi = process_sp->GetABI().get();
429     if (abi) {
430       m_unwind_plan_arch_default_at_func_entry_sp =
431           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
432       if (!abi->CreateFunctionEntryUnwindPlan(
433               *m_unwind_plan_arch_default_at_func_entry_sp)) {
434         m_unwind_plan_arch_default_at_func_entry_sp.reset();
435       }
436     }
437   }
438 
439   return m_unwind_plan_arch_default_at_func_entry_sp;
440 }
441 
442 Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) {
443   std::lock_guard<std::recursive_mutex> guard(m_mutex);
444   if (m_first_non_prologue_insn.IsValid())
445     return m_first_non_prologue_insn;
446 
447   ExecutionContext exe_ctx(target.shared_from_this(), false);
448   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
449   if (assembly_profiler_sp)
450     assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,
451                                                m_first_non_prologue_insn);
452   return m_first_non_prologue_insn;
453 }
454 
455 const Address &FuncUnwinders::GetFunctionStartAddress() const {
456   return m_range.GetBaseAddress();
457 }
458 
459 lldb::UnwindAssemblySP
460 FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {
461   UnwindAssemblySP assembly_profiler_sp;
462   if (ArchSpec arch = m_unwind_table.GetArchitecture()) {
463     arch.MergeFrom(target.GetArchitecture());
464     assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);
465   }
466   return assembly_profiler_sp;
467 }
468 
469 Address FuncUnwinders::GetLSDAAddress(Target &target) {
470   Address lsda_addr;
471 
472   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
473   if (unwind_plan_sp.get() == nullptr) {
474     unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
475   }
476   if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {
477     lsda_addr = unwind_plan_sp->GetLSDAAddress();
478   }
479   return lsda_addr;
480 }
481 
482 Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) {
483   Address personality_addr;
484 
485   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
486   if (unwind_plan_sp.get() == nullptr) {
487     unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
488   }
489   if (unwind_plan_sp.get() &&
490       unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {
491     personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
492   }
493 
494   return personality_addr;
495 }
496